@hanzo/ui 8.27.15 → 8.27.16

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 (178) hide show
  1. package/NOTICE +19 -0
  2. package/dist/agents/Attachments.cjs +29 -0
  3. package/dist/agents/Attachments.d.ts +31 -0
  4. package/dist/agents/Attachments.d.ts.map +1 -0
  5. package/dist/agents/Attachments.js +27 -0
  6. package/dist/agents/Attachments.js.map +1 -0
  7. package/dist/agents/Choice.cjs +47 -0
  8. package/dist/agents/Choice.d.ts +34 -0
  9. package/dist/agents/Choice.d.ts.map +1 -0
  10. package/dist/agents/Choice.js +44 -0
  11. package/dist/agents/Choice.js.map +1 -0
  12. package/dist/agents/Console.cjs +106 -0
  13. package/dist/agents/Console.d.ts +54 -0
  14. package/dist/agents/Console.d.ts.map +1 -0
  15. package/dist/agents/Console.js +104 -0
  16. package/dist/agents/Console.js.map +1 -0
  17. package/dist/agents/Feedback.cjs +50 -0
  18. package/dist/agents/Feedback.d.ts +25 -0
  19. package/dist/agents/Feedback.d.ts.map +1 -0
  20. package/dist/agents/Feedback.js +48 -0
  21. package/dist/agents/Feedback.js.map +1 -0
  22. package/dist/agents/FileTabs.cjs +63 -0
  23. package/dist/agents/FileTabs.d.ts +45 -0
  24. package/dist/agents/FileTabs.d.ts.map +1 -0
  25. package/dist/agents/FileTabs.js +61 -0
  26. package/dist/agents/FileTabs.js.map +1 -0
  27. package/dist/agents/FileTree.cjs +160 -0
  28. package/dist/agents/FileTree.d.ts +41 -0
  29. package/dist/agents/FileTree.d.ts.map +1 -0
  30. package/dist/agents/FileTree.js +157 -0
  31. package/dist/agents/FileTree.js.map +1 -0
  32. package/dist/agents/PreviewFrame.cjs +108 -0
  33. package/dist/agents/PreviewFrame.d.ts +78 -0
  34. package/dist/agents/PreviewFrame.d.ts.map +1 -0
  35. package/dist/agents/PreviewFrame.js +105 -0
  36. package/dist/agents/PreviewFrame.js.map +1 -0
  37. package/dist/agents/Suggestions.cjs +29 -0
  38. package/dist/agents/Suggestions.d.ts +28 -0
  39. package/dist/agents/Suggestions.d.ts.map +1 -0
  40. package/dist/agents/Suggestions.js +26 -0
  41. package/dist/agents/Suggestions.js.map +1 -0
  42. package/dist/agents/Workspace.cjs +103 -0
  43. package/dist/agents/Workspace.d.ts +104 -0
  44. package/dist/agents/Workspace.d.ts.map +1 -0
  45. package/dist/agents/Workspace.js +98 -0
  46. package/dist/agents/Workspace.js.map +1 -0
  47. package/dist/agents/bridge.cjs +201 -0
  48. package/dist/agents/bridge.d.ts +102 -0
  49. package/dist/agents/bridge.d.ts.map +1 -0
  50. package/dist/agents/bridge.js +197 -0
  51. package/dist/agents/bridge.js.map +1 -0
  52. package/dist/agents/index.cjs +64 -1
  53. package/dist/agents/index.d.ts +23 -0
  54. package/dist/agents/index.d.ts.map +1 -1
  55. package/dist/agents/index.js +23 -0
  56. package/dist/agents/index.js.map +1 -1
  57. package/dist/agents/log.cjs +75 -0
  58. package/dist/agents/log.d.ts +58 -0
  59. package/dist/agents/log.d.ts.map +1 -0
  60. package/dist/agents/log.js +65 -0
  61. package/dist/agents/log.js.map +1 -0
  62. package/dist/agents/tree.cjs +238 -0
  63. package/dist/agents/tree.d.ts +99 -0
  64. package/dist/agents/tree.d.ts.map +1 -0
  65. package/dist/agents/tree.js +226 -0
  66. package/dist/agents/tree.js.map +1 -0
  67. package/dist/backends/gui/3d-card.d.ts +6 -6
  68. package/dist/backends/gui/3d-marquee.d.ts +7 -8
  69. package/dist/backends/gui/3d-marquee.d.ts.map +1 -1
  70. package/dist/backends/gui/3d-pin.d.ts +1 -1
  71. package/dist/backends/gui/alert.d.ts +3 -3
  72. package/dist/backends/gui/android.d.ts +1 -1
  73. package/dist/backends/gui/animated-testimonials.d.ts +1 -1
  74. package/dist/backends/gui/animated-tooltip.d.ts +1 -1
  75. package/dist/backends/gui/announcement.d.ts +1 -1
  76. package/dist/backends/gui/banner.d.ts +1 -1
  77. package/dist/backends/gui/button.d.ts +1 -1
  78. package/dist/backends/gui/card.d.ts +7 -7
  79. package/dist/backends/gui/code-editor.cjs +2 -2
  80. package/dist/backends/gui/code-editor.d.ts +7 -1
  81. package/dist/backends/gui/code-editor.d.ts.map +1 -1
  82. package/dist/backends/gui/code-editor.js +2 -2
  83. package/dist/backends/gui/code-editor.js.map +1 -1
  84. package/dist/backends/gui/command.d.ts +5 -5
  85. package/dist/backends/gui/command.d.ts.map +1 -1
  86. package/dist/backends/gui/context-menu.d.ts +14 -14
  87. package/dist/backends/gui/context-menu.d.ts.map +1 -1
  88. package/dist/backends/gui/credit-card.d.ts +1 -1
  89. package/dist/backends/gui/desktop.d.ts +1 -1
  90. package/dist/backends/gui/dock.d.ts +3 -3
  91. package/dist/backends/gui/dropdown-menu.d.ts +16 -16
  92. package/dist/backends/gui/dropdown-menu.d.ts.map +1 -1
  93. package/dist/backends/gui/empty.d.ts +6 -6
  94. package/dist/backends/gui/field.d.ts +3 -3
  95. package/dist/backends/gui/gantt.d.ts +1 -1
  96. package/dist/backends/gui/grid-pattern.d.ts +1 -2
  97. package/dist/backends/gui/grid-pattern.d.ts.map +1 -1
  98. package/dist/backends/gui/image-zoom.d.ts +1 -1
  99. package/dist/backends/gui/iphone-15-pro.d.ts +1 -1
  100. package/dist/backends/gui/item.d.ts +9 -9
  101. package/dist/backends/gui/list.d.ts +2 -2
  102. package/dist/backends/gui/macos-dock.d.ts +2 -2
  103. package/dist/backends/gui/magnetic.d.ts +1 -1
  104. package/dist/backends/gui/marquee.d.ts +1 -15
  105. package/dist/backends/gui/marquee.d.ts.map +1 -1
  106. package/dist/backends/gui/menu-dock.d.ts +1 -1
  107. package/dist/backends/gui/menubar.d.ts +15 -15
  108. package/dist/backends/gui/menubar.d.ts.map +1 -1
  109. package/dist/backends/gui/message-dock.d.ts +1 -1
  110. package/dist/backends/gui/motion-highlight.d.ts +1 -12
  111. package/dist/backends/gui/motion-highlight.d.ts.map +1 -1
  112. package/dist/backends/gui/pagination.d.ts +4 -4
  113. package/dist/backends/gui/qr-code.d.ts +1 -2
  114. package/dist/backends/gui/qr-code.d.ts.map +1 -1
  115. package/dist/backends/gui/scroll-area.d.ts +3 -14
  116. package/dist/backends/gui/scroll-area.d.ts.map +1 -1
  117. package/dist/backends/gui/sheet.d.ts +3 -3
  118. package/dist/backends/gui/sheet.d.ts.map +1 -1
  119. package/dist/backends/gui/status.d.ts +1 -1
  120. package/dist/backends/gui/table.d.ts +8 -8
  121. package/dist/backends/gui/toaster.d.ts +1 -15
  122. package/dist/backends/gui/toaster.d.ts.map +1 -1
  123. package/dist/backends/gui/toggle.d.ts +1 -1
  124. package/dist/backends/gui/video-player.d.ts +1 -1
  125. package/dist/chat/Composer.cjs +60 -9
  126. package/dist/chat/Composer.d.ts +42 -2
  127. package/dist/chat/Composer.d.ts.map +1 -1
  128. package/dist/chat/Composer.js +61 -11
  129. package/dist/chat/Composer.js.map +1 -1
  130. package/dist/chat/EmptyPrompt.cjs +27 -0
  131. package/dist/chat/EmptyPrompt.d.ts +30 -0
  132. package/dist/chat/EmptyPrompt.d.ts.map +1 -0
  133. package/dist/chat/EmptyPrompt.js +24 -0
  134. package/dist/chat/EmptyPrompt.js.map +1 -0
  135. package/dist/chat/SessionRail.cjs +97 -0
  136. package/dist/chat/SessionRail.d.ts +97 -0
  137. package/dist/chat/SessionRail.d.ts.map +1 -0
  138. package/dist/chat/SessionRail.js +94 -0
  139. package/dist/chat/SessionRail.js.map +1 -0
  140. package/dist/chat/Thread.d.ts +2 -8
  141. package/dist/chat/Thread.d.ts.map +1 -1
  142. package/dist/chat/index.cjs +8 -1
  143. package/dist/chat/index.d.ts +3 -1
  144. package/dist/chat/index.d.ts.map +1 -1
  145. package/dist/chat/index.js +3 -1
  146. package/dist/chat/index.js.map +1 -1
  147. package/dist/gallery.cjs +28 -1
  148. package/dist/gallery.d.ts.map +1 -1
  149. package/dist/gallery.html +71 -3
  150. package/dist/gallery.js +30 -3
  151. package/dist/gallery.js.map +1 -1
  152. package/dist/product/BranchSelect.cjs +27 -0
  153. package/dist/product/BranchSelect.d.ts +27 -0
  154. package/dist/product/BranchSelect.d.ts.map +1 -0
  155. package/dist/product/BranchSelect.js +23 -0
  156. package/dist/product/BranchSelect.js.map +1 -0
  157. package/dist/product/ChipSelect.cjs +267 -0
  158. package/dist/product/ChipSelect.d.ts +71 -0
  159. package/dist/product/ChipSelect.d.ts.map +1 -0
  160. package/dist/product/ChipSelect.js +265 -0
  161. package/dist/product/ChipSelect.js.map +1 -0
  162. package/dist/product/RepoSelect.cjs +75 -0
  163. package/dist/product/RepoSelect.d.ts +63 -0
  164. package/dist/product/RepoSelect.d.ts.map +1 -0
  165. package/dist/product/RepoSelect.js +69 -0
  166. package/dist/product/RepoSelect.js.map +1 -0
  167. package/dist/product/chipSelect.logic.cjs +147 -0
  168. package/dist/product/chipSelect.logic.d.ts +92 -0
  169. package/dist/product/chipSelect.logic.d.ts.map +1 -0
  170. package/dist/product/chipSelect.logic.js +138 -0
  171. package/dist/product/chipSelect.logic.js.map +1 -0
  172. package/dist/product/index.cjs +23 -1
  173. package/dist/product/index.d.ts +4 -0
  174. package/dist/product/index.d.ts.map +1 -1
  175. package/dist/product/index.js +7 -0
  176. package/dist/product/index.js.map +1 -1
  177. package/dist/styles.css +68 -0
  178. package/package.json +2 -1
package/NOTICE CHANGED
@@ -4,3 +4,22 @@ Copyright (c) 2023 Hanzo AI, Inc.
4
4
  This product includes software from shadcn/ui (https://github.com/shadcn-ui/ui), licensed under MIT:
5
5
 
6
6
  Copyright (c) 2023 shadcn
7
+
8
+ This product includes software derived from Hanzo Build v2
9
+ (https://github.com/hanzoai/build-v2), licensed under MIT:
10
+
11
+ Copyright (c) 2025 Hanzo AI, Inc.
12
+
13
+ which is derived from OSW Studio (https://github.com/o-stahl/osw-studio),
14
+ licensed under MIT:
15
+
16
+ Copyright (c) 2025 Otto Stahl
17
+
18
+ which is itself derived from DeepSite v2
19
+ (https://huggingface.co/spaces/enzostvs/deepsite), by enzostvs and the
20
+ DeepSite authors, licensed under MIT.
21
+
22
+ The derived files are the builder workspace in pkg/ui/src/agents:
23
+ Workspace, Choice, FileTree, FileTabs, PreviewFrame, Console, Suggestions,
24
+ Attachments and Feedback (.tsx), and tree, log and bridge (.ts). The MIT
25
+ permission notice that governs them is the one in LICENSE-MIT.
@@ -0,0 +1,29 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Attachments = Attachments;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * Attachments — what the next turn is about, shown before it is sent.
8
+ *
9
+ * Ported from build-v2 `components/editor/ask-ai/{selected-files,
10
+ * selected-html-element}.tsx` (MIT, derived from OSW Studio and DeepSite — see
11
+ * NOTICE). v2 drew a file mention and a picked element as two different chips
12
+ * in two files; they are one fact — "this turn is about THAT" — so they are
13
+ * one row of chips, each a kind, a label and a way to take it back.
14
+ *
15
+ * Every label is TEXT: a picked element's tag and selector come from a page
16
+ * somebody else wrote, and a file's path from their repository.
17
+ */
18
+ const gui_1 = require("@hanzo/gui");
19
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
20
+ const slot_1 = require("../backends/gui/slot.cjs");
21
+ const ICON = { file: lucide_icons_2_1.FileText, element: lucide_icons_2_1.MousePointerClick, upload: lucide_icons_2_1.Paperclip };
22
+ function Attachments({ items, onRemove, ...rest }) {
23
+ if (items.length === 0)
24
+ return null;
25
+ return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('attachments'), render: "ul", "aria-label": "Attached to the next message", flexWrap: "wrap", gap: "$1.5", m: 0, p: 0, style: { listStyle: 'none' }, ...rest, children: items.map((item) => {
26
+ const Icon = ICON[item.kind];
27
+ return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { render: "li", items: "center", gap: "$1.5", minH: 24, pl: "$2", pr: onRemove ? '$1' : '$2', rounded: "$3", borderWidth: 1, borderColor: "$borderColor", bg: "$panel", maxW: "100%", children: [(0, jsx_runtime_1.jsx)(Icon, { size: 12, opacity: 0.7 }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$quiet", numberOfLines: 1, maxW: 220, children: item.label }), onRemove ? ((0, jsx_runtime_1.jsx)(gui_1.XStack, { render: "button", ...{ type: 'button', title: `Remove ${item.label}` }, "aria-label": `Remove ${item.label}`, onPress: () => onRemove(item.id), width: 20, height: 20, rounded: "$2", items: "center", justify: "center", bg: "transparent", borderWidth: 0, cursor: "pointer", hoverStyle: { bg: '$raised' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$rim' }, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.X, { size: 11 }) })) : null] }, item.id));
28
+ }) }));
29
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Attachments — what the next turn is about, shown before it is sent.
3
+ *
4
+ * Ported from build-v2 `components/editor/ask-ai/{selected-files,
5
+ * selected-html-element}.tsx` (MIT, derived from OSW Studio and DeepSite — see
6
+ * NOTICE). v2 drew a file mention and a picked element as two different chips
7
+ * in two files; they are one fact — "this turn is about THAT" — so they are
8
+ * one row of chips, each a kind, a label and a way to take it back.
9
+ *
10
+ * Every label is TEXT: a picked element's tag and selector come from a page
11
+ * somebody else wrote, and a file's path from their repository.
12
+ */
13
+ import { XStack } from '@hanzo/gui';
14
+ import type { ComponentProps } from 'react';
15
+ type Row = Omit<ComponentProps<typeof XStack>, 'children'>;
16
+ /** One thing the next turn is about. */
17
+ export interface Attachment {
18
+ id: string;
19
+ /** A repo file, a picked element, an uploaded file. */
20
+ kind: 'file' | 'element' | 'upload';
21
+ /** What the chip says: a path, `<button> .cta`, a file name. */
22
+ label: string;
23
+ }
24
+ export interface AttachmentsProps extends Row {
25
+ items: readonly Attachment[];
26
+ /** Omit and the chips cannot be removed. */
27
+ onRemove?: (id: string) => void;
28
+ }
29
+ export declare function Attachments({ items, onRemove, ...rest }: AttachmentsProps): import("react").JSX.Element | null;
30
+ export {};
31
+ //# sourceMappingURL=Attachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Attachments.d.ts","sourceRoot":"","sources":["../../src/agents/Attachments.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,OAAO,EAAe,MAAM,EAAE,MAAM,YAAY,CAAA;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAI3C,KAAK,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;AAE1D,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,uDAAuD;IACvD,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;IACnC,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAA;CACd;AAID,MAAM,WAAW,gBAAiB,SAAQ,GAAG;IAC3C,KAAK,EAAE,SAAS,UAAU,EAAE,CAAA;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,gBAAgB,sCA4DzE"}
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Attachments — what the next turn is about, shown before it is sent.
5
+ *
6
+ * Ported from build-v2 `components/editor/ask-ai/{selected-files,
7
+ * selected-html-element}.tsx` (MIT, derived from OSW Studio and DeepSite — see
8
+ * NOTICE). v2 drew a file mention and a picked element as two different chips
9
+ * in two files; they are one fact — "this turn is about THAT" — so they are
10
+ * one row of chips, each a kind, a label and a way to take it back.
11
+ *
12
+ * Every label is TEXT: a picked element's tag and selector come from a page
13
+ * somebody else wrote, and a file's path from their repository.
14
+ */
15
+ import { SizableText, XStack } from '@hanzo/gui';
16
+ import { FileText, MousePointerClick, Paperclip, X } from '@hanzogui/lucide-icons-2';
17
+ import { slot } from '../backends/gui/slot.js';
18
+ const ICON = { file: FileText, element: MousePointerClick, upload: Paperclip };
19
+ export function Attachments({ items, onRemove, ...rest }) {
20
+ if (items.length === 0)
21
+ return null;
22
+ return (_jsx(XStack, { ...slot('attachments'), render: "ul", "aria-label": "Attached to the next message", flexWrap: "wrap", gap: "$1.5", m: 0, p: 0, style: { listStyle: 'none' }, ...rest, children: items.map((item) => {
23
+ const Icon = ICON[item.kind];
24
+ return (_jsxs(XStack, { render: "li", items: "center", gap: "$1.5", minH: 24, pl: "$2", pr: onRemove ? '$1' : '$2', rounded: "$3", borderWidth: 1, borderColor: "$borderColor", bg: "$panel", maxW: "100%", children: [_jsx(Icon, { size: 12, opacity: 0.7 }), _jsx(SizableText, { size: "$1", color: "$quiet", numberOfLines: 1, maxW: 220, children: item.label }), onRemove ? (_jsx(XStack, { render: "button", ...{ type: 'button', title: `Remove ${item.label}` }, "aria-label": `Remove ${item.label}`, onPress: () => onRemove(item.id), width: 20, height: 20, rounded: "$2", items: "center", justify: "center", bg: "transparent", borderWidth: 0, cursor: "pointer", hoverStyle: { bg: '$raised' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$rim' }, children: _jsx(X, { size: 11 }) })) : null] }, item.id));
25
+ }) }));
26
+ }
27
+ //# sourceMappingURL=Attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Attachments.js","sourceRoot":"","sources":["../../src/agents/Attachments.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,0BAA0B,CAAA;AAGpF,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAa3C,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,SAAS,EAAW,CAAA;AAQvF,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAoB;IACxE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACnC,OAAO,CACL,KAAC,MAAM,OACD,IAAI,CAAC,aAAa,CAAC,EACvB,MAAM,EAAC,IAAI,gBACA,8BAA8B,EACzC,QAAQ,EAAC,MAAM,EACf,GAAG,EAAC,MAAM,EACV,CAAC,EAAE,CAAC,EACJ,CAAC,EAAE,CAAC,EACJ,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,KACxB,IAAI,YAEP,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC5B,OAAO,CACL,MAAC,MAAM,IAEL,MAAM,EAAC,IAAI,EACX,KAAK,EAAC,QAAQ,EACd,GAAG,EAAC,MAAM,EACV,IAAI,EAAE,EAAE,EACR,EAAE,EAAC,IAAI,EACP,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAC1B,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,EAAE,EAAC,QAAQ,EACX,IAAI,EAAC,MAAM,aAEX,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,GAAI,EAChC,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,EAAC,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,YAC9D,IAAI,CAAC,KAAK,GACC,EACb,QAAQ,CAAC,CAAC,CAAC,CACV,KAAC,MAAM,IACL,MAAM,EAAC,QAAQ,KACV,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAa,gBACrD,UAAU,IAAI,CAAC,KAAK,EAAE,EAClC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAChC,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,OAAO,EAAC,IAAI,EACZ,KAAK,EAAC,QAAQ,EACd,OAAO,EAAC,QAAQ,EAChB,EAAE,EAAC,aAAa,EAChB,WAAW,EAAE,CAAC,EACd,MAAM,EAAC,SAAS,EAChB,UAAU,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAC7B,iBAAiB,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,YAEnF,KAAC,CAAC,IAAC,IAAI,EAAE,EAAE,GAAI,GACR,CACV,CAAC,CAAC,CAAC,IAAI,KApCH,IAAI,CAAC,EAAE,CAqCL,CACV,CAAA;QACH,CAAC,CAAC,GACK,CACV,CAAA;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ModeSelect = ModeSelect;
5
+ exports.PageSelect = PageSelect;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ /**
8
+ * ModeSelect and PageSelect — pick one of a few, from a chip.
9
+ *
10
+ * Ported from build-v2 `components/editor/ask-ai` (the Build ⌄ mode chip) and
11
+ * `components/editor/header` (the page selector) (MIT, derived from OSW Studio
12
+ * and DeepSite — see NOTICE). Both are the same act — a label that says what
13
+ * is chosen and a menu of what else can be — so both are one `Choice` over the
14
+ * package's one `DropdownMenu`, which already owns the roving focus, the
15
+ * placement and the dismiss. They differ in dress only: a mode is a compact
16
+ * chip in a composer's row, a page is a wide field in the bar.
17
+ *
18
+ * WHAT A MODE MEANS IS THE HOST'S. `modes` is data; Build and Plan are the
19
+ * builder's two, and the hint under each is where the host says what the
20
+ * difference is ("edits, commits and pushes" / "plans without writing").
21
+ */
22
+ const gui_1 = require("@hanzo/gui");
23
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
24
+ const button_1 = require("../backends/gui/button.cjs");
25
+ const dropdown_menu_1 = require("../backends/gui/dropdown-menu.cjs");
26
+ const slot_1 = require("../backends/gui/slot.cjs");
27
+ function Choice({ options, value, onChange, label, placement = 'bottom-start', part, field, ...rest }) {
28
+ const chosen = options.find((o) => o.id === value) ?? options[0];
29
+ return ((0, jsx_runtime_1.jsx)(dropdown_menu_1.DropdownMenu, { placement: placement, trigger: (0, jsx_runtime_1.jsx)(button_1.Button, { ...(0, slot_1.slot)(part), type: "button", variant: field ? 'default' : 'ghost', size: "sm", "aria-label": `${label}: ${chosen?.label ?? 'none'}`, "aria-haspopup": "menu", minHeight: field ? 32 : 28, px: field ? '$3' : '$2', rounded: "$3", bg: field ? '$hover' : '$panel', justify: field ? 'center' : 'flex-start',
30
+ // A chip is as wide as its word, in a row or in a column.
31
+ self: "flex-start", ...rest, children: (0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1.5", minW: 0, children: [chosen?.icon ?? null, (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$ink", numberOfLines: 1, children: chosen?.label ?? '' }), (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 13, opacity: 0.6 })] }) }), items: options.map((o) => ({
32
+ key: o.id,
33
+ label: o.label,
34
+ description: o.hint,
35
+ icon: o.icon,
36
+ selected: o.id === value,
37
+ onSelect: () => onChange(o.id),
38
+ })) }));
39
+ }
40
+ /** The composer's mode chip — v2's Build ⌄. Opens upward: it sits at the bottom. */
41
+ function ModeSelect({ modes, label = 'Mode', placement = 'top-start', ...rest }) {
42
+ return (0, jsx_runtime_1.jsx)(Choice, { part: "mode-select", field: false, options: modes, label: label, placement: placement, ...rest });
43
+ }
44
+ /** The bar's page selector — v2's wide "Homepage ⌄" field. */
45
+ function PageSelect({ pages, label = 'Page', placement = 'bottom', ...rest }) {
46
+ return ((0, jsx_runtime_1.jsx)(Choice, { part: "page-select", field: true, options: pages, label: label, placement: placement, minW: 140, maxW: 200, ...rest }));
47
+ }
@@ -0,0 +1,34 @@
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+ import { Button } from '../backends/gui/button.js';
3
+ /** One thing to choose. */
4
+ export interface Option {
5
+ id: string;
6
+ label: string;
7
+ /** A second line in the menu: what choosing this does. */
8
+ hint?: string;
9
+ icon?: ReactNode;
10
+ }
11
+ type Trigger = Omit<ComponentProps<typeof Button>, 'children' | 'onChange' | 'value'>;
12
+ /** What every choice takes, whatever it chooses between. */
13
+ interface Chosen {
14
+ value: string;
15
+ onChange: (id: string) => void;
16
+ /** Where the menu opens relative to the chip. */
17
+ placement?: 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'bottom' | 'top';
18
+ }
19
+ export interface ModeSelectProps extends Chosen, Trigger {
20
+ modes: readonly Option[];
21
+ /** The control's accessible name. Defaults to "Mode". */
22
+ label?: string;
23
+ }
24
+ /** The composer's mode chip — v2's Build ⌄. Opens upward: it sits at the bottom. */
25
+ export declare function ModeSelect({ modes, label, placement, ...rest }: ModeSelectProps): import("react").JSX.Element;
26
+ export interface PageSelectProps extends Chosen, Trigger {
27
+ pages: readonly Option[];
28
+ /** The control's accessible name. Defaults to "Page". */
29
+ label?: string;
30
+ }
31
+ /** The bar's page selector — v2's wide "Homepage ⌄" field. */
32
+ export declare function PageSelect({ pages, label, placement, ...rest }: PageSelectProps): import("react").JSX.Element;
33
+ export {};
34
+ //# sourceMappingURL=Choice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Choice.d.ts","sourceRoot":"","sources":["../../src/agents/Choice.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAI/C,2BAA2B;AAC3B,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,KAAK,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,CAAA;AAErF,4DAA4D;AAC5D,UAAU,MAAM;IACd,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,iDAAiD;IACjD,SAAS,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,cAAc,GAAG,YAAY,GAAG,QAAQ,GAAG,KAAK,CAAA;CACvF;AA4DD,MAAM,WAAW,eAAgB,SAAQ,MAAM,EAAE,OAAO;IACtD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,KAAc,EAAE,SAAuB,EAAE,GAAG,IAAI,EAAE,EAAE,eAAe,+BAEtG;AAED,MAAM,WAAW,eAAgB,SAAQ,MAAM,EAAE,OAAO;IACtD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,KAAc,EAAE,SAAoB,EAAE,GAAG,IAAI,EAAE,EAAE,eAAe,+BAInG"}
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * ModeSelect and PageSelect — pick one of a few, from a chip.
5
+ *
6
+ * Ported from build-v2 `components/editor/ask-ai` (the Build ⌄ mode chip) and
7
+ * `components/editor/header` (the page selector) (MIT, derived from OSW Studio
8
+ * and DeepSite — see NOTICE). Both are the same act — a label that says what
9
+ * is chosen and a menu of what else can be — so both are one `Choice` over the
10
+ * package's one `DropdownMenu`, which already owns the roving focus, the
11
+ * placement and the dismiss. They differ in dress only: a mode is a compact
12
+ * chip in a composer's row, a page is a wide field in the bar.
13
+ *
14
+ * WHAT A MODE MEANS IS THE HOST'S. `modes` is data; Build and Plan are the
15
+ * builder's two, and the hint under each is where the host says what the
16
+ * difference is ("edits, commits and pushes" / "plans without writing").
17
+ */
18
+ import { SizableText, XStack } from '@hanzo/gui';
19
+ import { ChevronDown } from '@hanzogui/lucide-icons-2';
20
+ import { Button } from '../backends/gui/button.js';
21
+ import { DropdownMenu } from '../backends/gui/dropdown-menu.js';
22
+ import { slot } from '../backends/gui/slot.js';
23
+ function Choice({ options, value, onChange, label, placement = 'bottom-start', part, field, ...rest }) {
24
+ const chosen = options.find((o) => o.id === value) ?? options[0];
25
+ return (_jsx(DropdownMenu, { placement: placement, trigger: _jsx(Button, { ...slot(part), type: "button", variant: field ? 'default' : 'ghost', size: "sm", "aria-label": `${label}: ${chosen?.label ?? 'none'}`, "aria-haspopup": "menu", minHeight: field ? 32 : 28, px: field ? '$3' : '$2', rounded: "$3", bg: field ? '$hover' : '$panel', justify: field ? 'center' : 'flex-start',
26
+ // A chip is as wide as its word, in a row or in a column.
27
+ self: "flex-start", ...rest, children: _jsxs(XStack, { items: "center", gap: "$1.5", minW: 0, children: [chosen?.icon ?? null, _jsx(SizableText, { size: "$2", color: "$ink", numberOfLines: 1, children: chosen?.label ?? '' }), _jsx(ChevronDown, { size: 13, opacity: 0.6 })] }) }), items: options.map((o) => ({
28
+ key: o.id,
29
+ label: o.label,
30
+ description: o.hint,
31
+ icon: o.icon,
32
+ selected: o.id === value,
33
+ onSelect: () => onChange(o.id),
34
+ })) }));
35
+ }
36
+ /** The composer's mode chip — v2's Build ⌄. Opens upward: it sits at the bottom. */
37
+ export function ModeSelect({ modes, label = 'Mode', placement = 'top-start', ...rest }) {
38
+ return _jsx(Choice, { part: "mode-select", field: false, options: modes, label: label, placement: placement, ...rest });
39
+ }
40
+ /** The bar's page selector — v2's wide "Homepage ⌄" field. */
41
+ export function PageSelect({ pages, label = 'Page', placement = 'bottom', ...rest }) {
42
+ return (_jsx(Choice, { part: "page-select", field: true, options: pages, label: label, placement: placement, minW: 140, maxW: 200, ...rest }));
43
+ }
44
+ //# sourceMappingURL=Choice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Choice.js","sourceRoot":"","sources":["../../src/agents/Choice.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Console = Console;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * Console — the dock under the work: what the run and the page just said.
8
+ *
9
+ * Ported from build-v2 `components/editor/console/{index,dock,log}.tsx` (MIT,
10
+ * derived from OSW Studio and DeepSite — see NOTICE). v2 owned a module-scope
11
+ * buffer, a shell prompt that POSTed to its own backend and a sandbox stop
12
+ * button; here the lines are the host's (a run's events, a page's forwarded
13
+ * console), the shell is an optional `onRun`, and the dock is the frame and the
14
+ * one dimension it has.
15
+ *
16
+ * ONE DIMENSION. The dock is its height: `height > HEAD` is open, anything else
17
+ * shows the header alone. A drag, a click on the grip and an arrow key are all
18
+ * ways of setting that one number (`resolve` in `log.ts`), so a dragged size
19
+ * and a toggled state can never disagree. The host holds the number, so it can
20
+ * persist it with the rest of its chrome.
21
+ *
22
+ * Lines are TEXT. What a run prints and what a page logs is drawn as strings in
23
+ * a monospace block — never parsed as markup, never linkified, never run.
24
+ */
25
+ const gui_1 = require("@hanzo/gui");
26
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
27
+ const react_1 = require("react");
28
+ const button_1 = require("../backends/gui/button.cjs");
29
+ const gesture_1 = require("../backends/gui/gesture.cjs");
30
+ const input_1 = require("../backends/gui/input.cjs");
31
+ const slot_1 = require("../backends/gui/slot.cjs");
32
+ const log_1 = require("./log.cjs");
33
+ const TONE = {
34
+ log: '$ink',
35
+ info: '$ink',
36
+ warn: '$yellow10',
37
+ error: '$bad',
38
+ debug: '$soft',
39
+ };
40
+ const viewport = () => (typeof window === 'undefined' ? 1000 : window.innerHeight);
41
+ function Console({ lines, height, onHeight, tabs = [], tab = 'log', onTab, onClear, onRun, busy = false, status, label = 'Console', ...rest }) {
42
+ const open = (0, log_1.opened)(height);
43
+ const last = (0, react_1.useRef)(log_1.OPEN);
44
+ if (open)
45
+ last.current = height;
46
+ const start = (0, react_1.useRef)(null);
47
+ const tail = (0, react_1.useRef)(null);
48
+ const [command, setCommand] = (0, react_1.useState)('');
49
+ const counts = (0, log_1.count)([...lines]);
50
+ (0, react_1.useEffect)(() => {
51
+ if (open && tab === 'log')
52
+ tail.current?.scrollIntoView?.({ block: 'end' });
53
+ }, [lines.length, open, tab]);
54
+ const toggle = () => onHeight(open ? log_1.HEAD : (0, log_1.resolve)(last.current, viewport()));
55
+ const nudge = (delta) => onHeight((0, log_1.resolve)((open ? height : log_1.HEAD) + delta, viewport()));
56
+ const grip = (0, gesture_1.drag)({
57
+ begin: (e) => {
58
+ start.current = { y: e.clientY ?? 0, base: open ? height : log_1.HEAD, moved: false };
59
+ },
60
+ move: (e) => {
61
+ const s = start.current;
62
+ if (!s)
63
+ return;
64
+ const delta = s.y - (e.clientY ?? s.y);
65
+ if (Math.abs(delta) > 3)
66
+ s.moved = true;
67
+ if (s.moved)
68
+ onHeight((0, log_1.resolve)(s.base + delta, viewport()));
69
+ },
70
+ end: () => {
71
+ const s = start.current;
72
+ start.current = null;
73
+ if (s && !s.moved)
74
+ toggle();
75
+ },
76
+ });
77
+ const chosen = tabs.find((t) => t.id === tab);
78
+ const all = [{ id: 'log', label }, ...tabs];
79
+ return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('console'), render: "section", "aria-label": label, shrink: 0, minW: 0, overflow: "hidden", borderTopWidth: 1, borderColor: "$borderColor", bg: "$background", style: { height: Math.max(height, log_1.HEAD) }, ...rest, children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('console-grip'), role: "separator", "aria-orientation": "horizontal", "aria-label": `Resize ${label.toLowerCase()}`, "aria-valuemin": log_1.HEAD, "aria-valuemax": (0, log_1.ceiling)(viewport()), "aria-valuenow": Math.max(height, log_1.HEAD), tabIndex: 0, height: 6, mt: -3, cursor: "row-resize", hoverStyle: { bg: '$edge' }, focusVisibleStyle: { bg: '$rim' }, onKeyDown: ((e) => {
80
+ if (e.key === 'ArrowUp')
81
+ nudge(e.shiftKey ? log_1.STEP * 4 : log_1.STEP);
82
+ else if (e.key === 'ArrowDown')
83
+ nudge(-(e.shiftKey ? log_1.STEP * 4 : log_1.STEP));
84
+ else if (e.key === 'Enter' || e.key === ' ')
85
+ toggle();
86
+ else
87
+ return;
88
+ e.preventDefault();
89
+ }), ...grip }), (0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2", px: "$2", minH: log_1.HEAD - 6, shrink: 0, children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { role: "tablist", "aria-label": `${label} tabs`, items: "center", gap: "$1", minW: 0, shrink: 1, overflow: "scroll", children: all.map((t) => {
90
+ const on = t.id === tab;
91
+ return ((0, jsx_runtime_1.jsxs)(button_1.Button, { type: "button", variant: "ghost", size: "sm", role: "tab", "aria-selected": on, tabIndex: on ? 0 : -1, minHeight: 24, px: "$2", bg: on ? '$hover' : 'transparent', onClick: () => {
92
+ onTab?.(t.id);
93
+ if (!open)
94
+ toggle();
95
+ }, children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: on ? '$ink' : '$soft', children: t.label }), t.id === 'log' && counts.error > 0 ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$bad", ...(0, slot_1.slot)('console-errors'), children: counts.error })) : null] }, t.id));
96
+ }) }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1, minW: 0, justify: "flex-end", items: "center", gap: "$2", overflow: "hidden", children: status }), onClear && tab === 'log' ? ((0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", variant: "ghost", size: "icon-sm", minHeight: 24, minWidth: 24, "aria-label": `Clear ${label.toLowerCase()}`, title: `Clear ${label.toLowerCase()}`, disabled: lines.length === 0, onClick: onClear, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Trash2, { size: 13 }) })) : null, (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", variant: "ghost", size: "icon-sm", minHeight: 24, minWidth: 24, "aria-label": open ? `Collapse ${label.toLowerCase()}` : `Expand ${label.toLowerCase()}`, "aria-expanded": open, title: open ? 'Collapse' : 'Expand', onClick: toggle, children: open ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 14 }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronUp, { size: 14 }) })] }), open ? ((0, jsx_runtime_1.jsx)(gui_1.YStack, { role: "tabpanel", "aria-label": chosen?.label ?? label, flex: 1, minH: 0, children: chosen ? (chosen.content) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(gui_1.ScrollView, { flex: 1, minH: 0, children: (0, jsx_runtime_1.jsxs)(gui_1.YStack, { px: "$3", pb: "$2", ...(0, slot_1.slot)('console-lines'), role: "log", "aria-live": "polite", children: [lines.length === 0 ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$soft", fontFamily: "$mono", children: "Nothing yet." })) : (lines.map((l) => ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { gap: "$2", items: "flex-start", "data-level": l.level, children: [l.source ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$soft", fontFamily: "$mono", shrink: 0, children: l.source })) : null, (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: TONE[l.level], fontFamily: "$mono", flex: 1, minW: 0, whiteSpace: "pre-wrap", style: { wordBreak: 'break-word' }, children: l.text })] }, l.id)))), (0, jsx_runtime_1.jsx)("div", { ref: tail })] }) }), onRun ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2", px: "$3", py: "$1.5", borderTopWidth: 1, borderColor: "$borderColor", children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$soft", fontFamily: "$mono", "aria-hidden": true, children: "$" }), (0, jsx_runtime_1.jsx)(input_1.Input, { ...(0, slot_1.slot)('console-prompt'), value: command, disabled: busy, "aria-label": "Run a command", placeholder: busy ? 'Running…' : 'Run a command', onChangeText: setCommand, onKeyDown: ((e) => {
97
+ if (e.key !== 'Enter' || e.nativeEvent?.isComposing)
98
+ return;
99
+ const typed = command.trim();
100
+ if (!typed || busy)
101
+ return;
102
+ e.preventDefault();
103
+ onRun(typed);
104
+ setCommand('');
105
+ }), flex: 1, height: 28, borderWidth: 0, bg: "transparent", px: 0, fontFamily: "$mono", fontSize: "$1" })] })) : null] })) })) : null] }));
106
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Console — the dock under the work: what the run and the page just said.
3
+ *
4
+ * Ported from build-v2 `components/editor/console/{index,dock,log}.tsx` (MIT,
5
+ * derived from OSW Studio and DeepSite — see NOTICE). v2 owned a module-scope
6
+ * buffer, a shell prompt that POSTed to its own backend and a sandbox stop
7
+ * button; here the lines are the host's (a run's events, a page's forwarded
8
+ * console), the shell is an optional `onRun`, and the dock is the frame and the
9
+ * one dimension it has.
10
+ *
11
+ * ONE DIMENSION. The dock is its height: `height > HEAD` is open, anything else
12
+ * shows the header alone. A drag, a click on the grip and an arrow key are all
13
+ * ways of setting that one number (`resolve` in `log.ts`), so a dragged size
14
+ * and a toggled state can never disagree. The host holds the number, so it can
15
+ * persist it with the rest of its chrome.
16
+ *
17
+ * Lines are TEXT. What a run prints and what a page logs is drawn as strings in
18
+ * a monospace block — never parsed as markup, never linkified, never run.
19
+ */
20
+ import { YStack } from '@hanzo/gui';
21
+ import { type ComponentProps, type ReactNode } from 'react';
22
+ import { type Line } from './log.js';
23
+ type Col = Omit<ComponentProps<typeof YStack>, 'children' | 'height'>;
24
+ /** A tab beyond the log — a terminal, a run's raw output. */
25
+ export interface ConsoleTab {
26
+ id: string;
27
+ label: string;
28
+ /** What the tab shows when chosen. */
29
+ content: ReactNode;
30
+ }
31
+ export interface ConsoleProps extends Col {
32
+ /** The log. Newest last. */
33
+ lines: readonly Line[];
34
+ /** The dock's height, px. At or below `HEAD` only the header shows. */
35
+ height: number;
36
+ onHeight: (height: number) => void;
37
+ /** Tabs after the log. */
38
+ tabs?: readonly ConsoleTab[];
39
+ /** The chosen tab: `'log'` or one of `tabs`. */
40
+ tab?: string;
41
+ onTab?: (id: string) => void;
42
+ onClear?: () => void;
43
+ /** A command line under the log. Omit and there is none. */
44
+ onRun?: (command: string) => void;
45
+ /** A command is running: the line is held. */
46
+ busy?: boolean;
47
+ /** Right of the tabs: the branch, the run's state. */
48
+ status?: ReactNode;
49
+ /** The log tab's name. */
50
+ label?: string;
51
+ }
52
+ export declare function Console({ lines, height, onHeight, tabs, tab, onTab, onClear, onRun, busy, status, label, ...rest }: ConsoleProps): import("react").JSX.Element;
53
+ export {};
54
+ //# sourceMappingURL=Console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Console.d.ts","sourceRoot":"","sources":["../../src/agents/Console.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAmC,MAAM,EAAE,MAAM,YAAY,CAAA;AAEpE,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,SAAS,EAIf,MAAM,OAAO,CAAA;AAMd,OAAO,EAAoC,KAAK,IAAI,EAA+B,MAAM,OAAO,CAAA;AAEhG,KAAK,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAA;AAErE,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,OAAO,EAAE,SAAS,CAAA;CACnB;AAED,MAAM,WAAW,YAAa,SAAQ,GAAG;IACvC,4BAA4B;IAC5B,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IACtB,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,0BAA0B;IAC1B,IAAI,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;IAC5B,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,8CAA8C;IAC9C,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,sDAAsD;IACtD,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAYD,wBAAgB,OAAO,CAAC,EACtB,KAAK,EACL,MAAM,EACN,QAAQ,EACR,IAAS,EACT,GAAW,EACX,KAAK,EACL,OAAO,EACP,KAAK,EACL,IAAY,EACZ,MAAM,EACN,KAAiB,EACjB,GAAG,IAAI,EACR,EAAE,YAAY,+BAqNd"}
@@ -0,0 +1,104 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Console — the dock under the work: what the run and the page just said.
5
+ *
6
+ * Ported from build-v2 `components/editor/console/{index,dock,log}.tsx` (MIT,
7
+ * derived from OSW Studio and DeepSite — see NOTICE). v2 owned a module-scope
8
+ * buffer, a shell prompt that POSTed to its own backend and a sandbox stop
9
+ * button; here the lines are the host's (a run's events, a page's forwarded
10
+ * console), the shell is an optional `onRun`, and the dock is the frame and the
11
+ * one dimension it has.
12
+ *
13
+ * ONE DIMENSION. The dock is its height: `height > HEAD` is open, anything else
14
+ * shows the header alone. A drag, a click on the grip and an arrow key are all
15
+ * ways of setting that one number (`resolve` in `log.ts`), so a dragged size
16
+ * and a toggled state can never disagree. The host holds the number, so it can
17
+ * persist it with the rest of its chrome.
18
+ *
19
+ * Lines are TEXT. What a run prints and what a page logs is drawn as strings in
20
+ * a monospace block — never parsed as markup, never linkified, never run.
21
+ */
22
+ import { ScrollView, SizableText, XStack, YStack } from '@hanzo/gui';
23
+ import { ChevronDown, ChevronUp, Trash2 } from '@hanzogui/lucide-icons-2';
24
+ import { useEffect, useRef, useState, } from 'react';
25
+ import { Button } from '../backends/gui/button.js';
26
+ import { drag } from '../backends/gui/gesture.js';
27
+ import { Input } from '../backends/gui/input.js';
28
+ import { slot } from '../backends/gui/slot.js';
29
+ import { ceiling, count, HEAD, OPEN, opened, resolve, STEP } from './log.js';
30
+ const TONE = {
31
+ log: '$ink',
32
+ info: '$ink',
33
+ warn: '$yellow10',
34
+ error: '$bad',
35
+ debug: '$soft',
36
+ };
37
+ const viewport = () => (typeof window === 'undefined' ? 1000 : window.innerHeight);
38
+ export function Console({ lines, height, onHeight, tabs = [], tab = 'log', onTab, onClear, onRun, busy = false, status, label = 'Console', ...rest }) {
39
+ const open = opened(height);
40
+ const last = useRef(OPEN);
41
+ if (open)
42
+ last.current = height;
43
+ const start = useRef(null);
44
+ const tail = useRef(null);
45
+ const [command, setCommand] = useState('');
46
+ const counts = count([...lines]);
47
+ useEffect(() => {
48
+ if (open && tab === 'log')
49
+ tail.current?.scrollIntoView?.({ block: 'end' });
50
+ }, [lines.length, open, tab]);
51
+ const toggle = () => onHeight(open ? HEAD : resolve(last.current, viewport()));
52
+ const nudge = (delta) => onHeight(resolve((open ? height : HEAD) + delta, viewport()));
53
+ const grip = drag({
54
+ begin: (e) => {
55
+ start.current = { y: e.clientY ?? 0, base: open ? height : HEAD, moved: false };
56
+ },
57
+ move: (e) => {
58
+ const s = start.current;
59
+ if (!s)
60
+ return;
61
+ const delta = s.y - (e.clientY ?? s.y);
62
+ if (Math.abs(delta) > 3)
63
+ s.moved = true;
64
+ if (s.moved)
65
+ onHeight(resolve(s.base + delta, viewport()));
66
+ },
67
+ end: () => {
68
+ const s = start.current;
69
+ start.current = null;
70
+ if (s && !s.moved)
71
+ toggle();
72
+ },
73
+ });
74
+ const chosen = tabs.find((t) => t.id === tab);
75
+ const all = [{ id: 'log', label }, ...tabs];
76
+ return (_jsxs(YStack, { ...slot('console'), render: "section", "aria-label": label, shrink: 0, minW: 0, overflow: "hidden", borderTopWidth: 1, borderColor: "$borderColor", bg: "$background", style: { height: Math.max(height, HEAD) }, ...rest, children: [_jsx(YStack, { ...slot('console-grip'), role: "separator", "aria-orientation": "horizontal", "aria-label": `Resize ${label.toLowerCase()}`, "aria-valuemin": HEAD, "aria-valuemax": ceiling(viewport()), "aria-valuenow": Math.max(height, HEAD), tabIndex: 0, height: 6, mt: -3, cursor: "row-resize", hoverStyle: { bg: '$edge' }, focusVisibleStyle: { bg: '$rim' }, onKeyDown: ((e) => {
77
+ if (e.key === 'ArrowUp')
78
+ nudge(e.shiftKey ? STEP * 4 : STEP);
79
+ else if (e.key === 'ArrowDown')
80
+ nudge(-(e.shiftKey ? STEP * 4 : STEP));
81
+ else if (e.key === 'Enter' || e.key === ' ')
82
+ toggle();
83
+ else
84
+ return;
85
+ e.preventDefault();
86
+ }), ...grip }), _jsxs(XStack, { items: "center", gap: "$2", px: "$2", minH: HEAD - 6, shrink: 0, children: [_jsx(XStack, { role: "tablist", "aria-label": `${label} tabs`, items: "center", gap: "$1", minW: 0, shrink: 1, overflow: "scroll", children: all.map((t) => {
87
+ const on = t.id === tab;
88
+ return (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", role: "tab", "aria-selected": on, tabIndex: on ? 0 : -1, minHeight: 24, px: "$2", bg: on ? '$hover' : 'transparent', onClick: () => {
89
+ onTab?.(t.id);
90
+ if (!open)
91
+ toggle();
92
+ }, children: [_jsx(SizableText, { size: "$1", color: on ? '$ink' : '$soft', children: t.label }), t.id === 'log' && counts.error > 0 ? (_jsx(SizableText, { size: "$1", color: "$bad", ...slot('console-errors'), children: counts.error })) : null] }, t.id));
93
+ }) }), _jsx(XStack, { flex: 1, minW: 0, justify: "flex-end", items: "center", gap: "$2", overflow: "hidden", children: status }), onClear && tab === 'log' ? (_jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", minHeight: 24, minWidth: 24, "aria-label": `Clear ${label.toLowerCase()}`, title: `Clear ${label.toLowerCase()}`, disabled: lines.length === 0, onClick: onClear, children: _jsx(Trash2, { size: 13 }) })) : null, _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", minHeight: 24, minWidth: 24, "aria-label": open ? `Collapse ${label.toLowerCase()}` : `Expand ${label.toLowerCase()}`, "aria-expanded": open, title: open ? 'Collapse' : 'Expand', onClick: toggle, children: open ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronUp, { size: 14 }) })] }), open ? (_jsx(YStack, { role: "tabpanel", "aria-label": chosen?.label ?? label, flex: 1, minH: 0, children: chosen ? (chosen.content) : (_jsxs(_Fragment, { children: [_jsx(ScrollView, { flex: 1, minH: 0, children: _jsxs(YStack, { px: "$3", pb: "$2", ...slot('console-lines'), role: "log", "aria-live": "polite", children: [lines.length === 0 ? (_jsx(SizableText, { size: "$1", color: "$soft", fontFamily: "$mono", children: "Nothing yet." })) : (lines.map((l) => (_jsxs(XStack, { gap: "$2", items: "flex-start", "data-level": l.level, children: [l.source ? (_jsx(SizableText, { size: "$1", color: "$soft", fontFamily: "$mono", shrink: 0, children: l.source })) : null, _jsx(SizableText, { size: "$1", color: TONE[l.level], fontFamily: "$mono", flex: 1, minW: 0, whiteSpace: "pre-wrap", style: { wordBreak: 'break-word' }, children: l.text })] }, l.id)))), _jsx("div", { ref: tail })] }) }), onRun ? (_jsxs(XStack, { items: "center", gap: "$2", px: "$3", py: "$1.5", borderTopWidth: 1, borderColor: "$borderColor", children: [_jsx(SizableText, { size: "$1", color: "$soft", fontFamily: "$mono", "aria-hidden": true, children: "$" }), _jsx(Input, { ...slot('console-prompt'), value: command, disabled: busy, "aria-label": "Run a command", placeholder: busy ? 'Running…' : 'Run a command', onChangeText: setCommand, onKeyDown: ((e) => {
94
+ if (e.key !== 'Enter' || e.nativeEvent?.isComposing)
95
+ return;
96
+ const typed = command.trim();
97
+ if (!typed || busy)
98
+ return;
99
+ e.preventDefault();
100
+ onRun(typed);
101
+ setCommand('');
102
+ }), flex: 1, height: 28, borderWidth: 0, bg: "transparent", px: 0, fontFamily: "$mono", fontSize: "$1" })] })) : null] })) })) : null] }));
103
+ }
104
+ //# sourceMappingURL=Console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Console.js","sourceRoot":"","sources":["../../src/agents/Console.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Feedback = Feedback;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * Feedback — copy a reply, and say whether it was good.
8
+ *
9
+ * Ported from build-v2 `components/editor/ask-ai/chat-thread.tsx` (MIT, derived
10
+ * from OSW Studio and DeepSite — see NOTICE). It goes in `Message`'s `actions`
11
+ * slot, which is where chat already puts a turn's row of controls; v2 drew the
12
+ * same three buttons under every settled turn.
13
+ *
14
+ * The verdict is a toggle: pressing the chosen thumb again takes it back. Where
15
+ * it goes — an analytics event, a reward signal — is the host's `onVerdict`.
16
+ */
17
+ const gui_1 = require("@hanzo/gui");
18
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
19
+ const react_1 = require("react");
20
+ const button_1 = require("../backends/gui/button.cjs");
21
+ const slot_1 = require("../backends/gui/slot.cjs");
22
+ function Feedback({ text, verdict, onVerdict, ...rest }) {
23
+ const [held, setHeld] = (0, react_1.useState)(null);
24
+ const [copied, setCopied] = (0, react_1.useState)(false);
25
+ const timer = (0, react_1.useRef)(null);
26
+ (0, react_1.useEffect)(() => () => {
27
+ if (timer.current)
28
+ clearTimeout(timer.current);
29
+ }, []);
30
+ const current = verdict === undefined ? held : verdict;
31
+ const judge = (next) => {
32
+ const settled = current === next ? null : next;
33
+ setHeld(settled);
34
+ onVerdict?.(settled);
35
+ };
36
+ const copy = async () => {
37
+ if (!text)
38
+ return;
39
+ try {
40
+ await navigator.clipboard.writeText(text);
41
+ setCopied(true);
42
+ timer.current = setTimeout(() => setCopied(false), 1500);
43
+ }
44
+ catch {
45
+ /* a browser that refuses the clipboard leaves the button as it was */
46
+ }
47
+ };
48
+ const icon = { variant: 'ghost', size: 'icon-sm', minHeight: 28, minWidth: 28, type: 'button' };
49
+ return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('feedback'), items: "center", gap: 2, ...rest, children: [text ? ((0, jsx_runtime_1.jsx)(button_1.Button, { ...icon, "aria-label": copied ? 'Copied' : 'Copy reply', title: copied ? 'Copied' : 'Copy', onClick: copy, children: copied ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: 13 }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Copy, { size: 13 }) })) : null, (0, jsx_runtime_1.jsx)(button_1.Button, { ...icon, "aria-label": "Good result", title: "Good result", "aria-pressed": current === 'up', bg: current === 'up' ? '$raised' : 'transparent', onClick: () => judge('up'), children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ThumbsUp, { size: 13 }) }), (0, jsx_runtime_1.jsx)(button_1.Button, { ...icon, "aria-label": "Bad result", title: "Bad result", "aria-pressed": current === 'down', bg: current === 'down' ? '$raised' : 'transparent', onClick: () => judge('down'), children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ThumbsDown, { size: 13 }) })] }));
50
+ }