@hanzo/ui 8.27.3 → 8.27.5

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 (69) hide show
  1. package/dist/backdrop/Backdrop.cjs +420 -0
  2. package/dist/backdrop/Backdrop.d.ts +53 -0
  3. package/dist/backdrop/Backdrop.d.ts.map +1 -0
  4. package/dist/backdrop/Backdrop.js +418 -0
  5. package/dist/backdrop/Backdrop.js.map +1 -0
  6. package/dist/backdrop/index.cjs +50 -0
  7. package/dist/backdrop/index.d.ts +29 -0
  8. package/dist/backdrop/index.d.ts.map +1 -0
  9. package/dist/backdrop/index.js +29 -0
  10. package/dist/backdrop/index.js.map +1 -0
  11. package/dist/backdrop/scene.cjs +439 -0
  12. package/dist/backdrop/scene.d.ts +235 -0
  13. package/dist/backdrop/scene.d.ts.map +1 -0
  14. package/dist/backdrop/scene.js +423 -0
  15. package/dist/backdrop/scene.js.map +1 -0
  16. package/dist/backends/gui/select.cjs +38 -27
  17. package/dist/backends/gui/select.d.ts +14 -5
  18. package/dist/backends/gui/select.d.ts.map +1 -1
  19. package/dist/backends/gui/select.js +42 -31
  20. package/dist/backends/gui/select.js.map +1 -1
  21. package/dist/backends/gui/tooltip.cjs +22 -3
  22. package/dist/backends/gui/tooltip.d.ts +12 -4
  23. package/dist/backends/gui/tooltip.d.ts.map +1 -1
  24. package/dist/backends/gui/tooltip.js +22 -3
  25. package/dist/backends/gui/tooltip.js.map +1 -1
  26. package/dist/chat/Chat.cjs +23 -1
  27. package/dist/chat/Chat.d.ts +6 -3
  28. package/dist/chat/Chat.d.ts.map +1 -1
  29. package/dist/chat/Chat.js +23 -1
  30. package/dist/chat/Chat.js.map +1 -1
  31. package/dist/chat/Inspector.cjs +51 -0
  32. package/dist/chat/Inspector.d.ts +49 -0
  33. package/dist/chat/Inspector.d.ts.map +1 -0
  34. package/dist/chat/Inspector.js +49 -0
  35. package/dist/chat/Inspector.js.map +1 -0
  36. package/dist/chat/Message.cjs +3 -1
  37. package/dist/chat/Message.d.ts +3 -1
  38. package/dist/chat/Message.d.ts.map +1 -1
  39. package/dist/chat/Message.js +3 -1
  40. package/dist/chat/Message.js.map +1 -1
  41. package/dist/chat/Parts.cjs +159 -0
  42. package/dist/chat/Parts.d.ts +186 -0
  43. package/dist/chat/Parts.d.ts.map +1 -0
  44. package/dist/chat/Parts.js +153 -0
  45. package/dist/chat/Parts.js.map +1 -0
  46. package/dist/chat/Persona.cjs +34 -0
  47. package/dist/chat/Persona.d.ts +37 -0
  48. package/dist/chat/Persona.d.ts.map +1 -0
  49. package/dist/chat/Persona.js +30 -0
  50. package/dist/chat/Persona.js.map +1 -0
  51. package/dist/chat/Preview.cjs +42 -0
  52. package/dist/chat/Preview.d.ts +36 -0
  53. package/dist/chat/Preview.d.ts.map +1 -0
  54. package/dist/chat/Preview.js +40 -0
  55. package/dist/chat/Preview.js.map +1 -0
  56. package/dist/chat/directive.cjs +272 -0
  57. package/dist/chat/directive.d.ts +167 -0
  58. package/dist/chat/directive.d.ts.map +1 -0
  59. package/dist/chat/directive.js +266 -0
  60. package/dist/chat/directive.js.map +1 -0
  61. package/dist/chat/index.cjs +59 -4
  62. package/dist/chat/index.d.ts +31 -3
  63. package/dist/chat/index.d.ts.map +1 -1
  64. package/dist/chat/index.js +31 -3
  65. package/dist/chat/index.js.map +1 -1
  66. package/dist/gallery.html +4 -4
  67. package/dist/styles.css +3 -3
  68. package/dist/theme.css +3 -3
  69. package/package.json +7 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,OAAO,EAAQ,MAAM,EAAU,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE3D;wDACwD;AACxD,KAAK,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,CAAA;AAErE;;;;;;;GAOG;AACH,wBAAgB,KAAK,gCAEpB;AAED,MAAM,WAAW,YAAa,SAAQ,KAAK;IACzC,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;6DACyD;IACzD,IAAI,CAAC,EAAE,KAAK,CAAA;CACb;AAED,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,IAAY,EACZ,IAAI,EACJ,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,YAAY,+BAyDd"}
1
+ {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,OAAO,EAAQ,MAAM,EAAU,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE3D;wDACwD;AACxD,KAAK,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,CAAA;AAErE;;;;;;;GAOG;AACH,wBAAgB,KAAK,gCAEpB;AAED,MAAM,WAAW,YAAa,SAAQ,KAAK;IACzC,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;6DACyD;IACzD,IAAI,CAAC,EAAE,KAAK,CAAA;CACb;AAED,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,IAAY,EACZ,IAAI,EACJ,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,YAAY,+BAyDd"}
@@ -8,7 +8,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  * turn is a muted aside. The contrast is what says who is speaking, so there is
9
9
  * no name and no timestamp, and `icon` is opt-in.
10
10
  *
11
- * Content is `children`: the markdown pipeline stays with the surface.
11
+ * Content is `children`: the markdown pipeline stays with the surface. A turn
12
+ * that arrived as a list of parts puts `<Parts>` there — `Chat` does exactly
13
+ * that — so this component keeps knowing nothing about the wire.
12
14
  */
13
15
  import { Text, XStack, YStack } from '@hanzo/gui';
14
16
  import { ink } from '../backends/gui/ink.js';
@@ -1 +1 @@
1
- {"version":3,"file":"Message.js","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;GASG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAsB3C;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK;IACnB,OAAO,KAAC,MAAM,OAAK,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAC,MAAM,wBAAe,CAAA;AAC9F,CAAC;AAgBD,MAAM,UAAU,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,IAAI,GAAG,KAAK,EACZ,IAAI,EACJ,IAAI,EACJ,GAAG,KAAK,EACK;IACb,8EAA8E;IAC9E,4BAA4B;IAC5B,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM;QACtC,OAAO,CACL,KAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,eAIR,IAAI,EACf,KAAK,EAAC,MAAM,EACZ,OAAO,EAAC,QAAQ,EAChB,EAAE,EAAC,IAAI,KACH,KAAK,YAET,KAAC,IAAI,IAAC,QAAQ,EAAC,IAAI,EAAC,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,QAAQ,YAC5C,QAAQ,GACJ,GACA,CACV,CAAA;IAEH,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAA;IAC5B,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,eACR,IAAI,EACf,KAAK,EAAC,MAAM,EACZ,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,EACzC,GAAG,EAAC,IAAI;QACR,qEAAqE;QACrE,oDAAoD;QACpD,KAAK,WACD,KAAK,aAER,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,EAAE,EAAC,IAAI,YAAE,IAAI,GAAU,CAAC,CAAC,CAAC,IAAI,EACvD,MAAC,MAAM,OACD,IAAI,CAAC,cAAc,CAAC,iBACX,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACtC,GAAG,EAAC,IAAI;gBACR,yDAAyD;gBACzD,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAC3B,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KACtB,CAAC,IAAI,IAAI;oBACX,EAAE,EAAE,QAAQ;oBACZ,OAAO,EAAE,IAAI;oBACb,EAAE,EAAE,IAAI;oBACR,EAAE,EAAE,IAAI;iBACT,CAAC,KACE,IAAI,aAEP,GAAG,CAAC,QAAQ,CAAC,EACb,IAAI,CAAC,CAAC,CAAC,KAAC,KAAK,KAAG,CAAC,CAAC,CAAC,IAAI,EACvB,OAAO,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,GAAG,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,YAAE,OAAO,GAAU,CAAC,CAAC,CAAC,IAAI,IAC7D,IACF,CACV,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Message.js","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAsB3C;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK;IACnB,OAAO,KAAC,MAAM,OAAK,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAC,MAAM,wBAAe,CAAA;AAC9F,CAAC;AAgBD,MAAM,UAAU,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,IAAI,GAAG,KAAK,EACZ,IAAI,EACJ,IAAI,EACJ,GAAG,KAAK,EACK;IACb,8EAA8E;IAC9E,4BAA4B;IAC5B,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM;QACtC,OAAO,CACL,KAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,eAIR,IAAI,EACf,KAAK,EAAC,MAAM,EACZ,OAAO,EAAC,QAAQ,EAChB,EAAE,EAAC,IAAI,KACH,KAAK,YAET,KAAC,IAAI,IAAC,QAAQ,EAAC,IAAI,EAAC,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,QAAQ,YAC5C,QAAQ,GACJ,GACA,CACV,CAAA;IAEH,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAA;IAC5B,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,eACR,IAAI,EACf,KAAK,EAAC,MAAM,EACZ,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,EACzC,GAAG,EAAC,IAAI;QACR,qEAAqE;QACrE,oDAAoD;QACpD,KAAK,WACD,KAAK,aAER,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,EAAE,EAAC,IAAI,YAAE,IAAI,GAAU,CAAC,CAAC,CAAC,IAAI,EACvD,MAAC,MAAM,OACD,IAAI,CAAC,cAAc,CAAC,iBACX,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACtC,GAAG,EAAC,IAAI;gBACR,yDAAyD;gBACzD,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAC3B,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KACtB,CAAC,IAAI,IAAI;oBACX,EAAE,EAAE,QAAQ;oBACZ,OAAO,EAAE,IAAI;oBACb,EAAE,EAAE,IAAI;oBACR,EAAE,EAAE,IAAI;iBACT,CAAC,KACE,IAAI,aAEP,GAAG,CAAC,QAAQ,CAAC,EACb,IAAI,CAAC,CAAC,CAAC,KAAC,KAAK,KAAG,CAAC,CAAC,CAAC,IAAI,EACvB,OAAO,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,GAAG,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,YAAE,OAAO,GAAU,CAAC,CAAC,CAAC,IAAI,IAC7D,IACF,CACV,CAAA;AACH,CAAC"}
@@ -0,0 +1,159 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.show = void 0;
5
+ exports.join = join;
6
+ exports.Piece = Piece;
7
+ exports.Parts = Parts;
8
+ const jsx_runtime_1 = require("react/jsx-runtime");
9
+ /**
10
+ * Parts — a streamed turn, drawn by what each piece of it IS.
11
+ *
12
+ * A completion's content is a list of parts, and until now this package had one
13
+ * answer for all of them: `words` flattens the list to prose and DROPS every
14
+ * part that is not text. An image, a tool call, a citation, an artifact — all of
15
+ * it arrived on the wire and none of it reached the screen. Six surfaces wrote
16
+ * six switch statements over the same union to get it back.
17
+ *
18
+ * `MessagePart` is that union, closed, and `Parts` is the dispatcher over it.
19
+ * Closed is the decision: `words`'s `Part` stays OPEN because it reads the wire
20
+ * and must survive a type it has never heard of, while this one is the CANON —
21
+ * the set a surface can exhaustively handle, and the set this package promises
22
+ * to draw. A part whose `type` is outside it still contributes its text, exactly
23
+ * as `words` does, so an unknown part degrades to prose instead of vanishing.
24
+ *
25
+ * Nothing here is new furniture. Every branch dispatches to a piece this package
26
+ * already had: `Code` for a tool's arguments and its output, `Step` for the call
27
+ * itself, `Failure` for an error, `Sources` for citations, `ArtifactCard` for a
28
+ * produced thing. That is the whole reason a typed renderer belongs here rather
29
+ * than in each surface — the parts were already drawn, one per surface, with no
30
+ * agreement about which part got which drawing.
31
+ *
32
+ * MARKDOWN IS STILL NOT HERE. `prose` is where a surface's pipeline enters, and
33
+ * with none supplied the words render plainly. The plugin set is per-surface —
34
+ * nine plugins, one plugin, or a regex under a bundle ceiling that cannot afford
35
+ * a parser — so this package ships no parser and takes the rendered nodes.
36
+ */
37
+ const gui_1 = require("@hanzo/gui");
38
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
39
+ const Pane_1 = require("../agents/Pane.cjs");
40
+ const ink_1 = require("../backends/gui/ink.cjs");
41
+ const slot_1 = require("../backends/gui/slot.cjs");
42
+ const Code_1 = require("./Code.cjs");
43
+ const Failure_1 = require("./Failure.cjs");
44
+ const Preview_1 = require("./Preview.cjs");
45
+ const Sources_1 = require("./Sources.cjs");
46
+ const Step_1 = require("./Step.cjs");
47
+ /**
48
+ * Adjacent prose, put back together.
49
+ *
50
+ * The wire splits a sentence across parts — and mid-word, which is why `words`
51
+ * joins with no separator — so drawing each text part as its own block would
52
+ * break one paragraph into a dozen and hand a markdown parser fragments that are
53
+ * not markdown. Runs of `text` and runs of `reasoning` each collapse to one;
54
+ * everything else passes through untouched and in order.
55
+ *
56
+ * This is what makes `Parts` a strict improvement on `words` rather than a
57
+ * different-looking one: an all-text turn renders exactly the string `words`
58
+ * would have produced.
59
+ */
60
+ function join(parts) {
61
+ const out = [];
62
+ for (const part of parts) {
63
+ const last = out[out.length - 1];
64
+ if ((part.type === 'text' || part.type === 'reasoning') &&
65
+ last &&
66
+ last.type === part.type) {
67
+ out[out.length - 1] = { type: part.type, text: last.text + part.text };
68
+ continue;
69
+ }
70
+ out.push(part);
71
+ }
72
+ return out;
73
+ }
74
+ /**
75
+ * What a tool was asked, or answered, as text.
76
+ *
77
+ * The wire sends JSON, so a caller holding the parsed object should not have to
78
+ * re-serialise it at every call site — that is six copies of two lines. The
79
+ * fallback exists because this takes `unknown` and a value that cannot be
80
+ * serialised must not take the page down with it.
81
+ */
82
+ const show = (value) => {
83
+ if (value == null)
84
+ return '';
85
+ if (typeof value === 'string')
86
+ return value;
87
+ try {
88
+ return JSON.stringify(value, null, 2);
89
+ }
90
+ catch {
91
+ return String(value);
92
+ }
93
+ };
94
+ exports.show = show;
95
+ /** A size a person can read. Every surface writes this one; here it is once. */
96
+ const weigh = (bytes) => {
97
+ const units = ['B', 'KB', 'MB', 'GB'];
98
+ let n = bytes;
99
+ let i = 0;
100
+ while (n >= 1024 && i < units.length - 1) {
101
+ n /= 1024;
102
+ i += 1;
103
+ }
104
+ return `${i === 0 ? n : n.toFixed(1)} ${units[i]}`;
105
+ };
106
+ /**
107
+ * One part.
108
+ *
109
+ * It spreads no residual props and owns no box, which is the one place this
110
+ * package's house rule does not apply: a piece IS whichever component its type
111
+ * names, and giving it a wrapper of its own would put an anonymous div between
112
+ * every part and the column that spaces them. `Parts` is the box.
113
+ *
114
+ * Named `Piece` and not `Part` because `Part` is already the name of `words`'s
115
+ * open wire type on this barrel, and a module cannot export one name as both a
116
+ * type and a value.
117
+ */
118
+ function Piece({ part, prose, onRetry, onOpen, onSource }) {
119
+ switch (part.type) {
120
+ case 'text':
121
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: prose ? prose(part.text, part) : (0, ink_1.ink)(part.text) });
122
+ case 'reasoning':
123
+ // Dimmed rather than recoloured: a surface's markdown paints its own
124
+ // colours, and a token on the container would not reach inside them.
125
+ return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('reasoning'), opacity: 0.72, children: prose ? prose(part.text, part) : (0, ink_1.ink)(part.text) }));
126
+ case 'toolCall':
127
+ return ((0, jsx_runtime_1.jsx)(Step_1.Step, { name: part.name, status: "running", detail: part.id, children: part.args == null ? undefined : (0, jsx_runtime_1.jsx)(Code_1.Code, { language: "json", children: (0, exports.show)(part.args) }) }));
128
+ case 'toolResult':
129
+ return ((0, jsx_runtime_1.jsx)(Step_1.Step, { name: part.name, status: part.status ?? 'done', detail: part.id, children: part.result == null ? undefined : (0, jsx_runtime_1.jsx)(Code_1.Code, { language: "json", children: (0, exports.show)(part.result) }) }));
130
+ case 'image':
131
+ return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('image'), maxW: 420, rounded: "$4", overflow: "hidden", borderWidth: 1, borderColor: "$borderColor", children: (0, jsx_runtime_1.jsx)(gui_1.Image, { src: part.url, alt: part.alt ?? '', style: { width: '100%', height: 'auto', display: 'block' } }) }));
132
+ case 'file':
133
+ return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('file'), items: "center", gap: "$2", maxW: 420, px: "$2.5", py: "$2", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$panel", children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.Paperclip, { size: 13, color: "$quiet" }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$ink", numberOfLines: 1, flex: 1, children: part.name }), part.size == null ? null : ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$quiet", children: weigh(part.size) }))] }));
134
+ case 'citation':
135
+ return (0, jsx_runtime_1.jsx)(Sources_1.Sources, { sources: part.sources, onOpen: onSource });
136
+ case 'artifact':
137
+ // Held, so shown. `Preview` renders it with scripting disabled, which is
138
+ // what makes drawing model-authored markup a different question from
139
+ // loading a `uiResource`'s url — see that arm, and `Preview`'s own note.
140
+ return part.markup ? ((0, jsx_runtime_1.jsx)(Preview_1.Preview, { title: part.title, markup: part.markup })) : ((0, jsx_runtime_1.jsx)(Pane_1.ArtifactCard, { title: part.title, kind: part.kind, onOpen: onOpen ? () => onOpen(part) : undefined }));
141
+ case 'uiResource':
142
+ return ((0, jsx_runtime_1.jsx)(Step_1.Step, { name: part.uri, detail: part.mime, children: part.text ? (0, jsx_runtime_1.jsx)(Code_1.Code, { language: part.mime ?? 'text', children: part.text }) : undefined }));
143
+ case 'error':
144
+ return (0, jsx_runtime_1.jsx)(Failure_1.Failure, { onRetry: onRetry, children: part.text });
145
+ default: {
146
+ // The union is closed and the WIRE is not, which is the one place those
147
+ // two facts have to meet. A part this does not know contributes its text
148
+ // and nothing else — the same answer `words` gives, so nothing a surface
149
+ // sends can go missing without also having been missing before.
150
+ const unknown = part;
151
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: unknown.text ? (0, ink_1.ink)(unknown.text) : null });
152
+ }
153
+ }
154
+ }
155
+ /** A turn's parts, in order, spaced. Goes in a `Message`'s children — `Chat`
156
+ * puts it there for a turn whose content is a list. */
157
+ function Parts({ parts, prose, onRetry, onOpen, onSource, ...props }) {
158
+ return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('parts'), width: "100%", gap: "$2", ...props, children: join(parts).map((part, i) => ((0, jsx_runtime_1.jsx)(Piece, { part: part, prose: prose, onRetry: onRetry, onOpen: onOpen, onSource: onSource }, `${part.type}-${i}`))) }));
159
+ }
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Parts — a streamed turn, drawn by what each piece of it IS.
3
+ *
4
+ * A completion's content is a list of parts, and until now this package had one
5
+ * answer for all of them: `words` flattens the list to prose and DROPS every
6
+ * part that is not text. An image, a tool call, a citation, an artifact — all of
7
+ * it arrived on the wire and none of it reached the screen. Six surfaces wrote
8
+ * six switch statements over the same union to get it back.
9
+ *
10
+ * `MessagePart` is that union, closed, and `Parts` is the dispatcher over it.
11
+ * Closed is the decision: `words`'s `Part` stays OPEN because it reads the wire
12
+ * and must survive a type it has never heard of, while this one is the CANON —
13
+ * the set a surface can exhaustively handle, and the set this package promises
14
+ * to draw. A part whose `type` is outside it still contributes its text, exactly
15
+ * as `words` does, so an unknown part degrades to prose instead of vanishing.
16
+ *
17
+ * Nothing here is new furniture. Every branch dispatches to a piece this package
18
+ * already had: `Code` for a tool's arguments and its output, `Step` for the call
19
+ * itself, `Failure` for an error, `Sources` for citations, `ArtifactCard` for a
20
+ * produced thing. That is the whole reason a typed renderer belongs here rather
21
+ * than in each surface — the parts were already drawn, one per surface, with no
22
+ * agreement about which part got which drawing.
23
+ *
24
+ * MARKDOWN IS STILL NOT HERE. `prose` is where a surface's pipeline enters, and
25
+ * with none supplied the words render plainly. The plugin set is per-surface —
26
+ * nine plugins, one plugin, or a regex under a bundle ceiling that cannot afford
27
+ * a parser — so this package ships no parser and takes the rendered nodes.
28
+ */
29
+ import { YStack } from '@hanzo/gui';
30
+ import type { ComponentProps, ReactNode } from 'react';
31
+ import { type ArtifactKind } from '../agents/Pane.js';
32
+ import { type Source } from './Sources.js';
33
+ import { type Ran } from './Step.js';
34
+ /**
35
+ * One piece of a turn — the canonical set.
36
+ *
37
+ * Every member carries `type` and an optional `text`, which is what keeps
38
+ * `MessagePart[]` assignable to `words`'s `Part[]`: the same list answers "what
39
+ * was said" and "what is on screen" with no conversion between them.
40
+ *
41
+ * `toolCall` and `toolResult` are two states of one thing, not two things that
42
+ * arrive together — a streaming turn UPDATES the part in place as the result
43
+ * lands. A surface that appends both instead will see two steps, which is an
44
+ * honest picture of what it appended.
45
+ */
46
+ export type MessagePart =
47
+ /** Prose. */
48
+ {
49
+ type: 'text';
50
+ text: string;
51
+ }
52
+ /** Prose the model wrote while working, shown quieter than the answer. */
53
+ | {
54
+ type: 'reasoning';
55
+ text: string;
56
+ }
57
+ /** A tool the model asked for, and what it asked with. */
58
+ | {
59
+ type: 'toolCall';
60
+ name: string;
61
+ id?: string;
62
+ args?: unknown;
63
+ text?: string;
64
+ }
65
+ /** What the tool answered. `status` says how it went; absent means it landed. */
66
+ | {
67
+ type: 'toolResult';
68
+ name: string;
69
+ id?: string;
70
+ status?: Ran;
71
+ result?: unknown;
72
+ text?: string;
73
+ } | {
74
+ type: 'image';
75
+ url: string;
76
+ alt?: string;
77
+ text?: string;
78
+ } | {
79
+ type: 'file';
80
+ name: string;
81
+ url?: string;
82
+ mime?: string;
83
+ size?: number;
84
+ text?: string;
85
+ }
86
+ /** What the answer was drawn from. */
87
+ | {
88
+ type: 'citation';
89
+ sources: Source[];
90
+ text?: string;
91
+ }
92
+ /**
93
+ * Something the turn produced and the surface can open.
94
+ *
95
+ * `markup` is the thing ITSELF — a self-contained HTML document the model
96
+ * wrote — and when it is there the part draws as a `Preview` rather than as a
97
+ * card, because a card offering to open a thing we are holding is a worse
98
+ * answer than showing it. Absent, the card is all there is to draw.
99
+ */
100
+ | {
101
+ type: 'artifact';
102
+ title: string;
103
+ kind: ArtifactKind;
104
+ id?: string;
105
+ markup?: string;
106
+ text?: string;
107
+ }
108
+ /**
109
+ * A resource the model offers as an interface.
110
+ *
111
+ * Named and shown as source, never RUN. Executing a remote document inside the
112
+ * host page is the whole of cross-site scripting, and a component library
113
+ * cannot make that call for its consumers — a surface with a sandbox to run it
114
+ * in renders it itself, which is a decision it takes where its policy lives.
115
+ */
116
+ | {
117
+ type: 'uiResource';
118
+ uri: string;
119
+ mime?: string;
120
+ text?: string;
121
+ }
122
+ /** The turn did not arrive. */
123
+ | {
124
+ type: 'error';
125
+ text: string;
126
+ };
127
+ /**
128
+ * Adjacent prose, put back together.
129
+ *
130
+ * The wire splits a sentence across parts — and mid-word, which is why `words`
131
+ * joins with no separator — so drawing each text part as its own block would
132
+ * break one paragraph into a dozen and hand a markdown parser fragments that are
133
+ * not markdown. Runs of `text` and runs of `reasoning` each collapse to one;
134
+ * everything else passes through untouched and in order.
135
+ *
136
+ * This is what makes `Parts` a strict improvement on `words` rather than a
137
+ * different-looking one: an all-text turn renders exactly the string `words`
138
+ * would have produced.
139
+ */
140
+ export declare function join(parts: readonly MessagePart[]): MessagePart[];
141
+ /**
142
+ * What a tool was asked, or answered, as text.
143
+ *
144
+ * The wire sends JSON, so a caller holding the parsed object should not have to
145
+ * re-serialise it at every call site — that is six copies of two lines. The
146
+ * fallback exists because this takes `unknown` and a value that cannot be
147
+ * serialised must not take the page down with it.
148
+ */
149
+ export declare const show: (value: unknown) => string;
150
+ /** The controls a part can offer. Callbacks-out, as everything here is: the part
151
+ * is data and knows nothing about what opening it means. */
152
+ export interface PartActions {
153
+ /** Render prose. Absent, the words render plainly. */
154
+ prose?: (text: string, part: MessagePart) => ReactNode;
155
+ /** Run the turn again — an `error` part's control. Absent, none renders. */
156
+ onRetry?: () => void;
157
+ /** Open an `artifact` part. */
158
+ onOpen?: (part: Extract<MessagePart, {
159
+ type: 'artifact';
160
+ }>) => void;
161
+ /** Open one of a `citation` part's sources. */
162
+ onSource?: (source: Source) => void;
163
+ }
164
+ export interface PieceProps extends PartActions {
165
+ part: MessagePart;
166
+ }
167
+ /**
168
+ * One part.
169
+ *
170
+ * It spreads no residual props and owns no box, which is the one place this
171
+ * package's house rule does not apply: a piece IS whichever component its type
172
+ * names, and giving it a wrapper of its own would put an anonymous div between
173
+ * every part and the column that spaces them. `Parts` is the box.
174
+ *
175
+ * Named `Piece` and not `Part` because `Part` is already the name of `words`'s
176
+ * open wire type on this barrel, and a module cannot export one name as both a
177
+ * type and a value.
178
+ */
179
+ export declare function Piece({ part, prose, onRetry, onOpen, onSource }: PieceProps): import("react").JSX.Element;
180
+ export interface PartsProps extends PartActions, Omit<ComponentProps<typeof YStack>, 'children'> {
181
+ parts: readonly MessagePart[];
182
+ }
183
+ /** A turn's parts, in order, spaced. Goes in a `Message`'s children — `Chat`
184
+ * puts it there for a turn whose content is a list. */
185
+ export declare function Parts({ parts, prose, onRetry, onOpen, onSource, ...props }: PartsProps): import("react").JSX.Element;
186
+ //# sourceMappingURL=Parts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Parts.d.ts","sourceRoot":"","sources":["../../src/chat/Parts.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Parts — a streamed turn, drawn by what each piece of it IS.
5
+ *
6
+ * A completion's content is a list of parts, and until now this package had one
7
+ * answer for all of them: `words` flattens the list to prose and DROPS every
8
+ * part that is not text. An image, a tool call, a citation, an artifact — all of
9
+ * it arrived on the wire and none of it reached the screen. Six surfaces wrote
10
+ * six switch statements over the same union to get it back.
11
+ *
12
+ * `MessagePart` is that union, closed, and `Parts` is the dispatcher over it.
13
+ * Closed is the decision: `words`'s `Part` stays OPEN because it reads the wire
14
+ * and must survive a type it has never heard of, while this one is the CANON —
15
+ * the set a surface can exhaustively handle, and the set this package promises
16
+ * to draw. A part whose `type` is outside it still contributes its text, exactly
17
+ * as `words` does, so an unknown part degrades to prose instead of vanishing.
18
+ *
19
+ * Nothing here is new furniture. Every branch dispatches to a piece this package
20
+ * already had: `Code` for a tool's arguments and its output, `Step` for the call
21
+ * itself, `Failure` for an error, `Sources` for citations, `ArtifactCard` for a
22
+ * produced thing. That is the whole reason a typed renderer belongs here rather
23
+ * than in each surface — the parts were already drawn, one per surface, with no
24
+ * agreement about which part got which drawing.
25
+ *
26
+ * MARKDOWN IS STILL NOT HERE. `prose` is where a surface's pipeline enters, and
27
+ * with none supplied the words render plainly. The plugin set is per-surface —
28
+ * nine plugins, one plugin, or a regex under a bundle ceiling that cannot afford
29
+ * a parser — so this package ships no parser and takes the rendered nodes.
30
+ */
31
+ import { Image, SizableText, XStack, YStack } from '@hanzo/gui';
32
+ import { Paperclip } from '@hanzogui/lucide-icons-2';
33
+ import { ArtifactCard } from '../agents/Pane.js';
34
+ import { ink } from '../backends/gui/ink.js';
35
+ import { slot } from '../backends/gui/slot.js';
36
+ import { Code } from './Code.js';
37
+ import { Failure } from './Failure.js';
38
+ import { Preview } from './Preview.js';
39
+ import { Sources } from './Sources.js';
40
+ import { Step } from './Step.js';
41
+ /**
42
+ * Adjacent prose, put back together.
43
+ *
44
+ * The wire splits a sentence across parts — and mid-word, which is why `words`
45
+ * joins with no separator — so drawing each text part as its own block would
46
+ * break one paragraph into a dozen and hand a markdown parser fragments that are
47
+ * not markdown. Runs of `text` and runs of `reasoning` each collapse to one;
48
+ * everything else passes through untouched and in order.
49
+ *
50
+ * This is what makes `Parts` a strict improvement on `words` rather than a
51
+ * different-looking one: an all-text turn renders exactly the string `words`
52
+ * would have produced.
53
+ */
54
+ export function join(parts) {
55
+ const out = [];
56
+ for (const part of parts) {
57
+ const last = out[out.length - 1];
58
+ if ((part.type === 'text' || part.type === 'reasoning') &&
59
+ last &&
60
+ last.type === part.type) {
61
+ out[out.length - 1] = { type: part.type, text: last.text + part.text };
62
+ continue;
63
+ }
64
+ out.push(part);
65
+ }
66
+ return out;
67
+ }
68
+ /**
69
+ * What a tool was asked, or answered, as text.
70
+ *
71
+ * The wire sends JSON, so a caller holding the parsed object should not have to
72
+ * re-serialise it at every call site — that is six copies of two lines. The
73
+ * fallback exists because this takes `unknown` and a value that cannot be
74
+ * serialised must not take the page down with it.
75
+ */
76
+ export const show = (value) => {
77
+ if (value == null)
78
+ return '';
79
+ if (typeof value === 'string')
80
+ return value;
81
+ try {
82
+ return JSON.stringify(value, null, 2);
83
+ }
84
+ catch {
85
+ return String(value);
86
+ }
87
+ };
88
+ /** A size a person can read. Every surface writes this one; here it is once. */
89
+ const weigh = (bytes) => {
90
+ const units = ['B', 'KB', 'MB', 'GB'];
91
+ let n = bytes;
92
+ let i = 0;
93
+ while (n >= 1024 && i < units.length - 1) {
94
+ n /= 1024;
95
+ i += 1;
96
+ }
97
+ return `${i === 0 ? n : n.toFixed(1)} ${units[i]}`;
98
+ };
99
+ /**
100
+ * One part.
101
+ *
102
+ * It spreads no residual props and owns no box, which is the one place this
103
+ * package's house rule does not apply: a piece IS whichever component its type
104
+ * names, and giving it a wrapper of its own would put an anonymous div between
105
+ * every part and the column that spaces them. `Parts` is the box.
106
+ *
107
+ * Named `Piece` and not `Part` because `Part` is already the name of `words`'s
108
+ * open wire type on this barrel, and a module cannot export one name as both a
109
+ * type and a value.
110
+ */
111
+ export function Piece({ part, prose, onRetry, onOpen, onSource }) {
112
+ switch (part.type) {
113
+ case 'text':
114
+ return _jsx(_Fragment, { children: prose ? prose(part.text, part) : ink(part.text) });
115
+ case 'reasoning':
116
+ // Dimmed rather than recoloured: a surface's markdown paints its own
117
+ // colours, and a token on the container would not reach inside them.
118
+ return (_jsx(YStack, { ...slot('reasoning'), opacity: 0.72, children: prose ? prose(part.text, part) : ink(part.text) }));
119
+ case 'toolCall':
120
+ return (_jsx(Step, { name: part.name, status: "running", detail: part.id, children: part.args == null ? undefined : _jsx(Code, { language: "json", children: show(part.args) }) }));
121
+ case 'toolResult':
122
+ return (_jsx(Step, { name: part.name, status: part.status ?? 'done', detail: part.id, children: part.result == null ? undefined : _jsx(Code, { language: "json", children: show(part.result) }) }));
123
+ case 'image':
124
+ return (_jsx(YStack, { ...slot('image'), maxW: 420, rounded: "$4", overflow: "hidden", borderWidth: 1, borderColor: "$borderColor", children: _jsx(Image, { src: part.url, alt: part.alt ?? '', style: { width: '100%', height: 'auto', display: 'block' } }) }));
125
+ case 'file':
126
+ return (_jsxs(XStack, { ...slot('file'), items: "center", gap: "$2", maxW: 420, px: "$2.5", py: "$2", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$panel", children: [_jsx(Paperclip, { size: 13, color: "$quiet" }), _jsx(SizableText, { size: "$2", color: "$ink", numberOfLines: 1, flex: 1, children: part.name }), part.size == null ? null : (_jsx(SizableText, { size: "$1", color: "$quiet", children: weigh(part.size) }))] }));
127
+ case 'citation':
128
+ return _jsx(Sources, { sources: part.sources, onOpen: onSource });
129
+ case 'artifact':
130
+ // Held, so shown. `Preview` renders it with scripting disabled, which is
131
+ // what makes drawing model-authored markup a different question from
132
+ // loading a `uiResource`'s url — see that arm, and `Preview`'s own note.
133
+ return part.markup ? (_jsx(Preview, { title: part.title, markup: part.markup })) : (_jsx(ArtifactCard, { title: part.title, kind: part.kind, onOpen: onOpen ? () => onOpen(part) : undefined }));
134
+ case 'uiResource':
135
+ return (_jsx(Step, { name: part.uri, detail: part.mime, children: part.text ? _jsx(Code, { language: part.mime ?? 'text', children: part.text }) : undefined }));
136
+ case 'error':
137
+ return _jsx(Failure, { onRetry: onRetry, children: part.text });
138
+ default: {
139
+ // The union is closed and the WIRE is not, which is the one place those
140
+ // two facts have to meet. A part this does not know contributes its text
141
+ // and nothing else — the same answer `words` gives, so nothing a surface
142
+ // sends can go missing without also having been missing before.
143
+ const unknown = part;
144
+ return _jsx(_Fragment, { children: unknown.text ? ink(unknown.text) : null });
145
+ }
146
+ }
147
+ }
148
+ /** A turn's parts, in order, spaced. Goes in a `Message`'s children — `Chat`
149
+ * puts it there for a turn whose content is a list. */
150
+ export function Parts({ parts, prose, onRetry, onOpen, onSource, ...props }) {
151
+ return (_jsx(YStack, { ...slot('parts'), width: "100%", gap: "$2", ...props, children: join(parts).map((part, i) => (_jsx(Piece, { part: part, prose: prose, onRetry: onRetry, onOpen: onOpen, onSource: onSource }, `${part.type}-${i}`))) }));
152
+ }
153
+ //# sourceMappingURL=Parts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Parts.js","sourceRoot":"","sources":["../../src/chat/Parts.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGpD,OAAO,EAAE,YAAY,EAAqB,MAAM,gBAAgB,CAAA;AAChE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAe,MAAM,WAAW,CAAA;AAChD,OAAO,EAAE,IAAI,EAAY,MAAM,QAAQ,CAAA;AAwDvC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,IAAI,CAAC,KAA6B;IAChD,MAAM,GAAG,GAAkB,EAAE,CAAA;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAChC,IACE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC;YACnD,IAAI;YACJ,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EACvB,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;YACtE,SAAQ;QACV,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE;IAC7C,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,CAAA;IAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;AACH,CAAC,CAAA;AAED,gFAAgF;AAChF,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE;IACtC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;IACrC,IAAI,CAAC,GAAG,KAAK,CAAA;IACb,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,CAAC,IAAI,IAAI,CAAA;QACT,CAAC,IAAI,CAAC,CAAA;IACR,CAAC;IACD,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AACpD,CAAC,CAAA;AAmBD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAc;IAC1E,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,4BAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAI,CAAA;QAE/D,KAAK,WAAW;YACd,qEAAqE;YACrE,qEAAqE;YACrE,OAAO,CACL,KAAC,MAAM,OAAK,IAAI,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,IAAI,YACzC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GACzC,CACV,CAAA;QAEH,KAAK,UAAU;YACb,OAAO,CACL,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAC,SAAS,EAAC,MAAM,EAAE,IAAI,CAAC,EAAE,YACpD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAC,IAAI,IAAC,QAAQ,EAAC,MAAM,YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAQ,GAC1E,CACR,CAAA;QAEH,KAAK,YAAY;YACf,OAAO,CACL,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAClE,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAC,IAAI,IAAC,QAAQ,EAAC,MAAM,YAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAQ,GAC9E,CACR,CAAA;QAEH,KAAK,OAAO;YACV,OAAO,CACL,KAAC,MAAM,OACD,IAAI,CAAC,OAAO,CAAC,EACjB,IAAI,EAAE,GAAG,EACT,OAAO,EAAC,IAAI,EACZ,QAAQ,EAAC,QAAQ,EACjB,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,YAO1B,KAAC,KAAK,IACJ,GAAG,EAAE,IAAI,CAAC,GAAG,EACb,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE,EACnB,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAC1D,GACK,CACV,CAAA;QAEH,KAAK,MAAM;YACT,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,MAAM,CAAC,EAChB,KAAK,EAAC,QAAQ,EACd,GAAG,EAAC,IAAI,EACR,IAAI,EAAE,GAAG,EACT,EAAE,EAAC,MAAM,EACT,EAAE,EAAC,IAAI,EACP,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,EAAE,EAAC,QAAQ,aAEX,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAC,QAAQ,GAAG,EACtC,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,MAAM,EAAC,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,YAC1D,IAAI,CAAC,IAAI,GACE,EACb,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC1B,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,YAClC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GACL,CACf,IACM,CACV,CAAA;QAEH,KAAK,UAAU;YACb,OAAO,KAAC,OAAO,IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAI,CAAA;QAE7D,KAAK,UAAU;YACb,yEAAyE;YACzE,qEAAqE;YACrE,yEAAyE;YACzE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CACnB,KAAC,OAAO,IAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,GAAI,CACpD,CAAC,CAAC,CAAC,CACF,KAAC,YAAY,IACX,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,GAC/C,CACH,CAAA;QAEH,KAAK,YAAY;YACf,OAAO,CACL,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,YACpC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,IAAI,IAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,MAAM,YAAG,IAAI,CAAC,IAAI,GAAQ,CAAC,CAAC,CAAC,SAAS,GAC3E,CACR,CAAA;QAEH,KAAK,OAAO;YACV,OAAO,KAAC,OAAO,IAAC,OAAO,EAAE,OAAO,YAAG,IAAI,CAAC,IAAI,GAAW,CAAA;QAEzD,SAAS,CAAC;YACR,wEAAwE;YACxE,yEAAyE;YACzE,yEAAyE;YACzE,gEAAgE;YAChE,MAAM,OAAO,GAAG,IAAY,CAAA;YAC5B,OAAO,4BAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAI,CAAA;QACvD,CAAC;IACH,CAAC;AACH,CAAC;AAQD;wDACwD;AACxD,MAAM,UAAU,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAc;IACrF,OAAO,CACL,KAAC,MAAM,OAAK,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAC,MAAM,EAAC,GAAG,EAAC,IAAI,KAAK,KAAK,YACvD,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC5B,KAAC,KAAK,IAEJ,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,IALb,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,CAMxB,CACH,CAAC,GACK,CACV,CAAA;AACH,CAAC"}
@@ -0,0 +1,34 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.clip = void 0;
5
+ exports.Persona = Persona;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ /**
8
+ * Persona — a face on the canvas, and what it is doing.
9
+ *
10
+ * A persona is not a new engine. It is a MAPPING: an emotion names a clip, the
11
+ * clip goes to `Backdrop`'s `clips` mode, and that mode's preloaded crossfade
12
+ * does the switching it already does — one live frame over another, never a
13
+ * flash of black. So a mood change is a prop change, and there is exactly one
14
+ * piece of machinery playing video in this package rather than two.
15
+ *
16
+ * The mapping is the whole component, and it is deliberately thin. What an
17
+ * emotion MEANS — when a persona is listening, when it is thinking — belongs to
18
+ * whatever is driving the conversation; a component that guessed would be
19
+ * guessing from the one place with the least information.
20
+ *
21
+ * `idle` is required and every other emotion is optional, so a persona with one
22
+ * clip is a legal persona and adding a mood is adding a file. `clip` is pure and
23
+ * exported, which is what lets a surface preload the next mood, or test the
24
+ * mapping, without mounting anything.
25
+ */
26
+ const Backdrop_1 = require("../backdrop/Backdrop.cjs");
27
+ /** The clip for this emotion, falling back to idle. */
28
+ const clip = (scenes, emotion) => scenes[emotion] ?? scenes.idle;
29
+ exports.clip = clip;
30
+ function Persona({ scenes, emotion = 'idle', ...props }) {
31
+ // One clip, so it loops itself rather than ending and handing over — a mood
32
+ // holds until something changes it, which is what a mood is.
33
+ return (0, jsx_runtime_1.jsx)(Backdrop_1.Backdrop, { ...props, mode: "clips", clips: [(0, exports.clip)(scenes, emotion)] });
34
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Persona — a face on the canvas, and what it is doing.
3
+ *
4
+ * A persona is not a new engine. It is a MAPPING: an emotion names a clip, the
5
+ * clip goes to `Backdrop`'s `clips` mode, and that mode's preloaded crossfade
6
+ * does the switching it already does — one live frame over another, never a
7
+ * flash of black. So a mood change is a prop change, and there is exactly one
8
+ * piece of machinery playing video in this package rather than two.
9
+ *
10
+ * The mapping is the whole component, and it is deliberately thin. What an
11
+ * emotion MEANS — when a persona is listening, when it is thinking — belongs to
12
+ * whatever is driving the conversation; a component that guessed would be
13
+ * guessing from the one place with the least information.
14
+ *
15
+ * `idle` is required and every other emotion is optional, so a persona with one
16
+ * clip is a legal persona and adding a mood is adding a file. `clip` is pure and
17
+ * exported, which is what lets a surface preload the next mood, or test the
18
+ * mapping, without mounting anything.
19
+ */
20
+ import { type BackdropProps } from '../backdrop/Backdrop.js';
21
+ /** What a persona is doing. The set a conversation can actually report. */
22
+ export type Emotion = 'idle' | 'listening' | 'thinking' | 'speaking' | 'happy' | 'sad' | 'surprised';
23
+ /** Which clip plays for each emotion. `idle` is required: it is what plays when
24
+ * a persona has nothing for the emotion at hand, so there is always something
25
+ * on the canvas and never a gap to design around. */
26
+ export type Scenes = {
27
+ idle: string;
28
+ } & Partial<Record<Emotion, string>>;
29
+ /** The clip for this emotion, falling back to idle. */
30
+ export declare const clip: (scenes: Scenes, emotion: Emotion) => string;
31
+ export interface PersonaProps extends Omit<BackdropProps, 'mode' | 'clips'> {
32
+ scenes: Scenes;
33
+ /** What the persona is doing right now. Defaults to idle. */
34
+ emotion?: Emotion;
35
+ }
36
+ export declare function Persona({ scenes, emotion, ...props }: PersonaProps): import("react").JSX.Element;
37
+ //# sourceMappingURL=Persona.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Persona.d.ts","sourceRoot":"","sources":["../../src/chat/Persona.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEnE,2EAA2E;AAC3E,MAAM,MAAM,OAAO,GACf,MAAM,GACN,WAAW,GACX,UAAU,GACV,UAAU,GACV,OAAO,GACP,KAAK,GACL,WAAW,CAAA;AAEf;;sDAEsD;AACtD,MAAM,MAAM,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;AAExE,uDAAuD;AACvD,eAAO,MAAM,IAAI,WAAY,MAAM,WAAW,OAAO,KAAG,MAAwC,CAAA;AAEhG,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,OAAgB,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY,+BAI3E"}