@hanzo/rooms 0.1.64 → 0.1.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Chat.js +4 -3
- package/dist/Rail.js +10 -6
- package/dist/RightPane.d.ts +5 -14
- package/dist/RightPane.js +20 -56
- package/dist/lib/host.d.ts +5 -0
- package/dist/lib/host.js +5 -0
- package/package.json +3 -3
package/dist/Chat.js
CHANGED
|
@@ -58,10 +58,10 @@ import { FileText, Image as ImageMark, Paperclip, X } from "lucide-react";
|
|
|
58
58
|
import { FREE } from "./lib/ai.js";
|
|
59
59
|
import { openThread, useOpen } from "./open.js";
|
|
60
60
|
import { Beside, Framed } from "./Shell.js";
|
|
61
|
-
import { SEED,
|
|
61
|
+
import { SEED, look, useSections, useSites } from "./RightPane.js";
|
|
62
62
|
import { Share } from "./Share.js";
|
|
63
63
|
import { ConversationMenu, ThreadMore, useThreadList } from "./thread.js";
|
|
64
|
-
import { artifacts, lead, nameOf, PAGE, Panel, PanelToggle, prompt, renders, Reply, Served, useDeck, useKey, useMind, usePanel, frames, name as tabName, } from "@hanzo/build";
|
|
64
|
+
import { artifacts, lead, nameOf, PAGE, Panel, PanelToggle, prompt, renders, Reply, Served, Summary, useDeck, useKey, useMind, usePanel, frames, name as tabName, } from "@hanzo/build";
|
|
65
65
|
import { checkoutUrl } from './lib/pay.js';
|
|
66
66
|
import { Upgrade, useFree } from './Upgrade.js';
|
|
67
67
|
import { enter, LOGIN } from './lib/destination.js';
|
|
@@ -1222,6 +1222,7 @@ function Thread({ placeholder = message(), initial, anonymous = false, heading,
|
|
|
1222
1222
|
// Dev place goes from a host without it (hanzo.team).
|
|
1223
1223
|
const pathed = useRooms().path !== null;
|
|
1224
1224
|
const create = () => (pathed ? go(app("")) : window.location.assign(dev()));
|
|
1225
|
+
const sections = useSections({ at, said, held: files, deck, onCreate: create });
|
|
1225
1226
|
/** The tabs' browser, as this conversation offers it: the org's sites to start from, and a page asked about, captured or opened in Dev. */
|
|
1226
1227
|
const browsing = {
|
|
1227
1228
|
suggested: sites,
|
|
@@ -1274,7 +1275,7 @@ function Thread({ placeholder = message(), initial, anonymous = false, heading,
|
|
|
1274
1275
|
e.preventDefault();
|
|
1275
1276
|
// A dropped folder arrives as entries; each file under it goes up with its path.
|
|
1276
1277
|
void dropped(e.dataTransfer).then((list) => hold(at, list, via));
|
|
1277
|
-
}, children: [dragging ? (_jsx(YStack, { "aria-hidden": true, position: "absolute", t: 0, r: 0, b: 0, l: 0, z: 10, items: "center", justify: "center", bg: "var(--surface-scrim)", borderWidth: 2, borderStyle: "dashed", borderColor: "$borderColor", rounded: "var(--pane-round)", pointerEvents: "none", children: _jsxs(XStack, { items: "center", gap: "$2", px: "$4", py: "$2.5", rounded: "$10", bg: "$background", borderWidth: 1, borderColor: "$borderColor", children: [_jsx(Paperclip, { size: 15, "aria-hidden": true }), _jsx(Text, { fontSize: "$4", color: "$ink", children: "Drop files to attach" })] }) })) : null, _jsxs(XStack, { "data-slot": "conversation-head", height: 52, items: "center", justify: "space-between", gap: "$3", pl: "$4", pr: "$2", shrink: 0, children: [_jsxs(XStack, { items: "center", gap: "$2", minW: 0, flex: 1, children: [mine ? (_jsx(Text, { fontSize: 15, lineHeight: 20, color: "$ink", numberOfLines: 1, shrink: 1, minW: 0, children: mine.title || "Untitled" })) : null, room.length ? (_jsx(XStack, { role: "list", "aria-label": "Agents in this chat", items: "center", gap: "$1.5", minW: 0, overflowX: "auto", "$platform-web": { scrollbarWidth: "none" }, children: room.map((name) => (_jsxs(XStack, { role: "listitem", items: "center", gap: "$1.5", pl: "$1", pr: "$0.5", py: "$0.5", rounded: 999, borderWidth: 1, borderColor: "$borderColor", shrink: 0, children: [_jsx(Face, { src: faces[name]?.avatar ?? (name === withWhom ? portrait : undefined), emoji: faces[name]?.emoji ?? (name === withWhom ? persona?.emoji : undefined), name: name, size: 22 }), _jsx(Text, { fontSize: "$2", fontWeight: "600", color: "$color", numberOfLines: 1, display: "none", $sm: { display: "flex" }, children: name }), _jsx(Box, { render: "button", onClick: () => openAgent(name), "aria-label": `Remove ${name} from this chat`, title: `Remove ${name}`, width: 24, height: 24, rounded: 999, items: "center", justify: "center", hoverStyle: { bg: "$hover" }, children: _jsx(X, { size: 13, "aria-hidden": true, color: "var(--soft, var(--muted-foreground))" }) })] }, name))) })) : null] }), _jsxs(XStack, { "data-slot": "conversation-controls", items: "center", gap: 2, shrink: 0, children: [open ? _jsx(Share, { thread: open }) : null, mine ? (_jsx(ConversationMenu, { threads: alone, active: open, children: _jsx(XStack, { children: _jsx(ThreadMore, { t: mine }) }) })) : null, _jsx(Summary, {
|
|
1278
|
+
}, children: [dragging ? (_jsx(YStack, { "aria-hidden": true, position: "absolute", t: 0, r: 0, b: 0, l: 0, z: 10, items: "center", justify: "center", bg: "var(--surface-scrim)", borderWidth: 2, borderStyle: "dashed", borderColor: "$borderColor", rounded: "var(--pane-round)", pointerEvents: "none", children: _jsxs(XStack, { items: "center", gap: "$2", px: "$4", py: "$2.5", rounded: "$10", bg: "$background", borderWidth: 1, borderColor: "$borderColor", children: [_jsx(Paperclip, { size: 15, "aria-hidden": true }), _jsx(Text, { fontSize: "$4", color: "$ink", children: "Drop files to attach" })] }) })) : null, _jsxs(XStack, { "data-slot": "conversation-head", height: 52, items: "center", justify: "space-between", gap: "$3", pl: "$4", pr: "$2", shrink: 0, children: [_jsxs(XStack, { items: "center", gap: "$2", minW: 0, flex: 1, children: [mine ? (_jsx(Text, { fontSize: 15, lineHeight: 20, color: "$ink", numberOfLines: 1, shrink: 1, minW: 0, children: mine.title || "Untitled" })) : null, room.length ? (_jsx(XStack, { role: "list", "aria-label": "Agents in this chat", items: "center", gap: "$1.5", minW: 0, overflowX: "auto", "$platform-web": { scrollbarWidth: "none" }, children: room.map((name) => (_jsxs(XStack, { role: "listitem", items: "center", gap: "$1.5", pl: "$1", pr: "$0.5", py: "$0.5", rounded: 999, borderWidth: 1, borderColor: "$borderColor", shrink: 0, children: [_jsx(Face, { src: faces[name]?.avatar ?? (name === withWhom ? portrait : undefined), emoji: faces[name]?.emoji ?? (name === withWhom ? persona?.emoji : undefined), name: name, size: 22 }), _jsx(Text, { fontSize: "$2", fontWeight: "600", color: "$color", numberOfLines: 1, display: "none", $sm: { display: "flex" }, children: name }), _jsx(Box, { render: "button", onClick: () => openAgent(name), "aria-label": `Remove ${name} from this chat`, title: `Remove ${name}`, width: 24, height: 24, rounded: 999, items: "center", justify: "center", hoverStyle: { bg: "$hover" }, children: _jsx(X, { size: 13, "aria-hidden": true, color: "var(--soft, var(--muted-foreground))" }) })] }, name))) })) : null] }), _jsxs(XStack, { "data-slot": "conversation-controls", items: "center", gap: 2, shrink: 0, children: [open ? _jsx(Share, { thread: open }) : null, mine ? (_jsx(ConversationMenu, { threads: alone, active: open, children: _jsx(XStack, { children: _jsx(ThreadMore, { t: mine }) }) })) : null, _jsx(Summary, { sections: sections, onOpen: () => setPanel(true) }), _jsx(PanelToggle, { open: panel, onToggle: () => setPanel(!panel) })] })] }), wide && aside !== null ? (_jsx(Beside, { children: _jsx(Panel, { side: deck, kinds: NONE, onHide: () => setPanel(false), label: "Tabs", ...browsing }) })) : null, !wide && panel ? _jsx(Panel, { side: deck, kinds: NONE, sheet: true, onHide: () => setPanel(false), label: "Tabs", ...browsing }) : null, isFree(model) ? (_jsxs(Text, { fontSize: "$2", color: "$soft", text: "center", maxW: MEASURE, mx: "auto", px: "$4", py: "$2", children: [freeCopy.notice, " ", _jsx(Anchor, { href: site("/legal/privacy"), children: freeCopy.noticeCta })] })) : null, _jsx(ChatSurface, { ...chat, messages: shown, send: guarded,
|
|
1278
1279
|
// AN EMPTY ROOM CENTRES ITS COMPOSER. While nothing has been said the
|
|
1279
1280
|
// opening (the heading and the starters) and the composer sit as one
|
|
1280
1281
|
// group in the middle of the height, with or without the plan bars in
|
package/dist/Rail.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
// The app's rail: its products as marks down the window's left edge, in one
|
|
4
|
-
// order — Chat, Dev, Library, Scheduled tasks, Customize — then More, a
|
|
5
|
-
// the rest, and the account at the foot. It is how the app moves
|
|
6
|
-
//
|
|
4
|
+
// order — Chat, Dev, Studio, Library, Scheduled tasks, Customize — then More, a
|
|
5
|
+
// menu of the rest, and the account at the foot. It is how the app moves
|
|
6
|
+
// between its products; there is no switch anywhere else.
|
|
7
|
+
//
|
|
8
|
+
// Studio is its own page, hanzo.ai/studio, opened in this tab: the app draws it
|
|
9
|
+
// there for a signed-in reader.
|
|
7
10
|
//
|
|
8
11
|
// Library, Scheduled tasks and Customize are Dev's own places (@hanzo/build's
|
|
9
12
|
// Artifacts, Automations and Customize), raised to the rail; each is lit while
|
|
@@ -19,12 +22,13 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
19
22
|
// rail lies along the foot of the drawer (`flat`), the account at its end; the
|
|
20
23
|
// drawer is too narrow for every mark, so Library, Scheduled tasks and
|
|
21
24
|
// Customize lead More there.
|
|
22
|
-
import { Boxes, Clock, Code2, Ellipsis, FolderGit2, LayoutTemplate, Library, ListTodo, MessageSquare, PanelLeft, Puzzle, Server, SquareTerminal, Users } from 'lucide-react';
|
|
25
|
+
import { Boxes, Clock, Code2, Ellipsis, FolderGit2, LayoutTemplate, Library, ListTodo, MessageSquare, PanelLeft, Puzzle, Server, SquareTerminal, Users, WandSparkles } from 'lucide-react';
|
|
23
26
|
import { XStack, YStack } from '@hanzo/gui';
|
|
24
27
|
import { route } from '@hanzo/build';
|
|
25
28
|
import { DropdownMenu } from '@hanzo/ui';
|
|
26
29
|
import { Me } from './Me.js';
|
|
27
|
-
import { app, TABS, WORKSPACE } from './lib/host.js';
|
|
30
|
+
import { app, STUDIO, TABS, WORKSPACE } from './lib/host.js';
|
|
31
|
+
import { site } from './where.js';
|
|
28
32
|
/** The rail's width, px. */
|
|
29
33
|
export const RAIL = 48;
|
|
30
34
|
/** A mark, px: a 36px square on a 44px pitch. */
|
|
@@ -91,5 +95,5 @@ export function Rail({ host, mode, at, open, toggle, flat = false, onChat, onDev
|
|
|
91
95
|
{ key: 'team', label: 'Team', icon: _jsx(Users, { size: 16, "aria-hidden": true }), onSelect: () => out(WORKSPACE) },
|
|
92
96
|
];
|
|
93
97
|
const Stack = flat ? XStack : YStack;
|
|
94
|
-
return (_jsxs(Stack, { "data-slot": "rail", render: "nav", "aria-label": "Products", ...(flat ? { pt: '$2', mt: '$2', borderTopWidth: 1, borderColor: '$borderColor', gap: '$1' } : { width: RAIL, flex: 1, pt: '$2', pb: '$2', gap: 8 }), shrink: 0, items: "center", children: [toggle ? (_jsx(YStack, { pb: 8, children: _jsx(Toggle, { open: open, onPress: toggle }) })) : null, _jsx(Mark, { label: "Chat", on: mode === 'chat', onPress: onChat, "data-slot": "rail-chat", children: _jsx(MessageSquare, { size: 18, "aria-hidden": true }) }), _jsx(Mark, { label: "Dev", on: mode === 'dev' && !here, onPress: onDev, "data-slot": "rail-dev", children: _jsx(Code2, { size: 18, "aria-hidden": true }) }), flat ? null : (_jsxs(_Fragment, { children: [_jsx(Mark, { label: "Library", on: here === 'library', onPress: to(RAISED.library), "data-slot": "rail-library", children: _jsx(Library, { size: 18, "aria-hidden": true }) }), _jsx(Mark, { label: "Scheduled tasks", on: here === 'scheduled', onPress: to(RAISED.scheduled), "data-slot": "rail-scheduled", children: _jsx(Clock, { size: 18, "aria-hidden": true }) }), _jsx(Mark, { label: "Customize", on: here === 'customize', onPress: to(RAISED.customize), "data-slot": "rail-customize", children: _jsx(Puzzle, { size: 18, "aria-hidden": true }) })] })), _jsx(DropdownMenu, { placement: flat ? 'top-start' : 'right-start', minWidth: 220, trigger: _jsx(XStack, { render: "button", "aria-label": "More", ...{ title: 'More' }, "data-slot": "rail-more", width: MARK, height: MARK, rounded: "$4", items: "center", justify: "center", cursor: "pointer", opacity: 0.62, hoverStyle: { bg: '$hover', opacity: 1 }, pressStyle: { bg: '$raised' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, $touchable: { width: 44, height: 44 }, children: _jsx(Ellipsis, { size: 18, "aria-hidden": true }) }), items: rest }), _jsx(YStack, { flex: 1 }), _jsx(Me, { host: host, narrow: true, above: flat, onOrg: onOrg })] }));
|
|
98
|
+
return (_jsxs(Stack, { "data-slot": "rail", render: "nav", "aria-label": "Products", ...(flat ? { pt: '$2', mt: '$2', borderTopWidth: 1, borderColor: '$borderColor', gap: '$1' } : { width: RAIL, flex: 1, pt: '$2', pb: '$2', gap: 8 }), shrink: 0, items: "center", children: [toggle ? (_jsx(YStack, { pb: 8, children: _jsx(Toggle, { open: open, onPress: toggle }) })) : null, _jsx(Mark, { label: "Chat", on: mode === 'chat', onPress: onChat, "data-slot": "rail-chat", children: _jsx(MessageSquare, { size: 18, "aria-hidden": true }) }), _jsx(Mark, { label: "Dev", on: mode === 'dev' && !here, onPress: onDev, "data-slot": "rail-dev", children: _jsx(Code2, { size: 18, "aria-hidden": true }) }), _jsx(Mark, { label: "Studio", onPress: () => window.location.assign(site(STUDIO)), "data-slot": "rail-studio", children: _jsx(WandSparkles, { size: 18, "aria-hidden": true }) }), flat ? null : (_jsxs(_Fragment, { children: [_jsx(Mark, { label: "Library", on: here === 'library', onPress: to(RAISED.library), "data-slot": "rail-library", children: _jsx(Library, { size: 18, "aria-hidden": true }) }), _jsx(Mark, { label: "Scheduled tasks", on: here === 'scheduled', onPress: to(RAISED.scheduled), "data-slot": "rail-scheduled", children: _jsx(Clock, { size: 18, "aria-hidden": true }) }), _jsx(Mark, { label: "Customize", on: here === 'customize', onPress: to(RAISED.customize), "data-slot": "rail-customize", children: _jsx(Puzzle, { size: 18, "aria-hidden": true }) })] })), _jsx(DropdownMenu, { placement: flat ? 'top-start' : 'right-start', minWidth: 220, trigger: _jsx(XStack, { render: "button", "aria-label": "More", ...{ title: 'More' }, "data-slot": "rail-more", width: MARK, height: MARK, rounded: "$4", items: "center", justify: "center", cursor: "pointer", opacity: 0.62, hoverStyle: { bg: '$hover', opacity: 1 }, pressStyle: { bg: '$raised' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, $touchable: { width: 44, height: 44 }, children: _jsx(Ellipsis, { size: 18, "aria-hidden": true }) }), items: rest }), _jsx(YStack, { flex: 1 }), _jsx(Me, { host: host, narrow: true, above: flat, onOrg: onOrg })] }));
|
|
95
99
|
}
|
package/dist/RightPane.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ChatMessage } from '@hanzo/ai/react';
|
|
2
|
-
import { type Deck, type
|
|
2
|
+
import { type Deck, type Section, type Tabs } from '@hanzo/build';
|
|
3
3
|
import { type Api } from './lib/files.js';
|
|
4
4
|
import { type Held } from './pane.js';
|
|
5
5
|
/** A conversation's panel before anyone has arranged it. */
|
|
@@ -31,28 +31,19 @@ export interface Mark {
|
|
|
31
31
|
* the bytes this document still holds first (`localOf`).
|
|
32
32
|
*/
|
|
33
33
|
export declare function look(deck: Deck, m: Mark, api: Api): Promise<void>;
|
|
34
|
-
/** Chat's kinds of tab, over the conversation `said` and the files `held` for the next message. */
|
|
35
|
-
export declare function useKinds({ at, said, held, deck }: {
|
|
36
|
-
at: string;
|
|
37
|
-
said: ChatMessage[];
|
|
38
|
-
held: Held[];
|
|
39
|
-
deck: Deck;
|
|
40
|
-
}): Kind[];
|
|
41
34
|
/**
|
|
42
|
-
* The conversation's summary
|
|
35
|
+
* The conversation's summary as sections (@hanzo/build `Summary`): what it
|
|
43
36
|
* produced (Outputs, led by Create file or site, which starts a Dev run) and
|
|
44
37
|
* what went into it (Sources, with the `+` that brings more). Each row opens in
|
|
45
|
-
* a tab beside the conversation.
|
|
46
|
-
* and one quiet line.
|
|
38
|
+
* a tab beside the conversation.
|
|
47
39
|
*/
|
|
48
|
-
export declare function
|
|
40
|
+
export declare function useSections({ at, said, held, deck, onCreate }: {
|
|
49
41
|
at: string;
|
|
50
42
|
said: ChatMessage[];
|
|
51
43
|
held: Held[];
|
|
52
44
|
deck: Deck;
|
|
53
|
-
onOpen: () => void;
|
|
54
45
|
onCreate: () => void;
|
|
55
|
-
}):
|
|
46
|
+
}): Section[];
|
|
56
47
|
/**
|
|
57
48
|
* The organization's sites, as an empty tab suggests them: `GET /v1/projects`,
|
|
58
49
|
* every row with a live address. Read once a conversation; nothing on a refusal.
|
package/dist/RightPane.js
CHANGED
|
@@ -17,11 +17,10 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
17
17
|
// @hanzo/build (`useDeck`, scope `chat:<channel>`); the frame owns the column
|
|
18
18
|
// it stands in (`Beside` in `Shell.tsx`).
|
|
19
19
|
import { useEffect, useMemo, useState } from 'react';
|
|
20
|
-
import { FileCode, Globe, Image as ImageMark,
|
|
21
|
-
import { Box, DropdownMenu, DropdownMenuContent, DropdownMenuCheckboxItem, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger,
|
|
20
|
+
import { FileCode, Globe, Image as ImageMark, Paperclip, Plus } from 'lucide-react';
|
|
21
|
+
import { Box, DropdownMenu, DropdownMenuContent, DropdownMenuCheckboxItem, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, Text, } from '@hanzo/ui';
|
|
22
22
|
import { useAi } from '@hanzo/ai/react';
|
|
23
23
|
import { artifacts, name as titleOf, PAGE } from '@hanzo/build';
|
|
24
|
-
import { Card, Quiet, Row } from './card.js';
|
|
25
24
|
import { said as told } from './lib/attach.js';
|
|
26
25
|
import { download, fileOf } from './lib/files.js';
|
|
27
26
|
import { org, scope } from './lib/session.js';
|
|
@@ -116,32 +115,6 @@ export async function look(deck, m, api) {
|
|
|
116
115
|
// A file forgotten or a store unreachable opens nothing; the row stays.
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
|
-
/** A list of marks, every one of them; pressing one opens it. */
|
|
120
|
-
function Marks({ kind, title, icon, marks, deck, action, children }) {
|
|
121
|
-
const ai = useAi();
|
|
122
|
-
return (_jsxs(Card, { kind: kind, icon: icon, title: title, action: action, children: [marks.length === 0 ? _jsx(Quiet, { children: children }) : null, marks.map((m) => {
|
|
123
|
-
const Glyph = GLYPH[m.kind];
|
|
124
|
-
return (_jsx(Row, { icon: _jsx(Glyph, { size: 16, "aria-hidden": true }), onPress: () => void look(deck, m, ai), children: m.name }, m.id));
|
|
125
|
-
})] }));
|
|
126
|
-
}
|
|
127
|
-
/** Chat's kinds of tab, over the conversation `said` and the files `held` for the next message. */
|
|
128
|
-
export function useKinds({ at, said, held, deck }) {
|
|
129
|
-
const made = useMemo(() => outputs(said), [said]);
|
|
130
|
-
const took = useMemo(() => sources(said, held), [said, held]);
|
|
131
|
-
const done = useMemo(() => lookups(said), [said]);
|
|
132
|
-
return [
|
|
133
|
-
{
|
|
134
|
-
id: 'artifacts',
|
|
135
|
-
label: 'Artifacts',
|
|
136
|
-
render: () => (_jsx(Marks, { kind: "outputs", title: "Outputs", icon: _jsx(FileCode, { size: 16, "aria-hidden": true }), marks: made, deck: deck, children: "This conversation has produced nothing yet." })),
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
id: 'sources',
|
|
140
|
-
label: 'Sources',
|
|
141
|
-
render: () => (_jsxs(YStack, { gap: "$3", children: [_jsx(Marks, { kind: "sources", title: "Sources", icon: _jsx(Paperclip, { size: 16, "aria-hidden": true }), marks: took, deck: deck, action: _jsx(Add, { at: at }), children: "Nothing has been put into this conversation yet." }), _jsxs(Card, { kind: "lookups", icon: _jsx(Search, { size: 16, "aria-hidden": true }), title: "Looked up", children: [done.length === 0 ? _jsx(Quiet, { children: "Nothing was looked up for this conversation yet." }) : null, done.map((call) => (_jsxs(YStack, { gap: "$1", p: "$2", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", children: [_jsx(Text, { fontSize: "$2", color: "$ink", children: call.name }), _jsx(Text, { fontSize: "$1", color: "$soft", numberOfLines: 2, children: call.asked }), _jsx(Text, { fontSize: "$1", color: "$soft", numberOfLines: 6, children: call.got ?? 'Running…' })] }, call.id)))] })] })),
|
|
142
|
-
},
|
|
143
|
-
];
|
|
144
|
-
}
|
|
145
118
|
/**
|
|
146
119
|
* A menu row's words.
|
|
147
120
|
*
|
|
@@ -218,40 +191,31 @@ function Services() {
|
|
|
218
191
|
.catch((e) => setStep(String(e?.message ?? 'Could not start')));
|
|
219
192
|
}, children: _jsx(Word, { children: p.name }) }, p.id)))] }));
|
|
220
193
|
}
|
|
221
|
-
/** A row of the summary: its mark and its name, one press from a tab. */
|
|
222
|
-
function Line({ icon, children, onPress, quiet = false }) {
|
|
223
|
-
return (_jsxs(XStack, { render: onPress ? 'button' : undefined, role: onPress ? 'button' : undefined, onPress: onPress, items: "center", gap: "$2.5", px: "$2", minH: 30, width: "100%", rounded: "$3", cursor: onPress ? 'pointer' : undefined, hoverStyle: onPress ? { bg: '$hover' } : undefined, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, children: [icon ? (_jsx(XStack, { width: 16, justify: "center", shrink: 0, opacity: 0.75, children: icon })) : null, _jsx(Text, { flex: 1, minW: 0, fontSize: "$2", color: quiet ? '$soft' : '$ink', numberOfLines: 1, children: children })] }));
|
|
224
|
-
}
|
|
225
|
-
/** A heading of the summary, with what it adds at its end. */
|
|
226
|
-
const Head = ({ children, action }) => (_jsxs(XStack, { items: "center", justify: "space-between", px: "$2", pt: "$1.5", pb: "$1", minH: 28, children: [_jsx(Text, { fontSize: "$2", color: "$soft", children: children }), action] }));
|
|
227
194
|
/**
|
|
228
|
-
* The conversation's summary
|
|
195
|
+
* The conversation's summary as sections (@hanzo/build `Summary`): what it
|
|
229
196
|
* produced (Outputs, led by Create file or site, which starts a Dev run) and
|
|
230
197
|
* what went into it (Sources, with the `+` that brings more). Each row opens in
|
|
231
|
-
* a tab beside the conversation.
|
|
232
|
-
* and one quiet line.
|
|
198
|
+
* a tab beside the conversation.
|
|
233
199
|
*/
|
|
234
|
-
export function
|
|
200
|
+
export function useSections({ at, said, held, deck, onCreate }) {
|
|
235
201
|
const ai = useAi();
|
|
236
|
-
const [open, setOpen] = useState(false);
|
|
237
202
|
const made = useMemo(() => outputs(said), [said]);
|
|
238
203
|
const took = useMemo(() => sources(said, held), [said, held]);
|
|
239
204
|
const done = useMemo(() => lookups(said), [said]);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}), !done.length && !took.length ? _jsx(Line, { quiet: true, children: "Nothing yet" }) : null] }) })] }));
|
|
205
|
+
return useMemo(() => {
|
|
206
|
+
const row = (m) => {
|
|
207
|
+
const Glyph = GLYPH[m.kind];
|
|
208
|
+
return { id: m.id, title: m.name, icon: _jsx(Glyph, { size: 15, "aria-hidden": true }), open: () => void look(deck, m, ai) };
|
|
209
|
+
};
|
|
210
|
+
const asked = done.map((call) => {
|
|
211
|
+
const m = { id: call.id, name: call.name, kind: 'file', body: [call.asked, call.got ?? ''].filter(Boolean).join('\n\n'), mime: 'text/plain' };
|
|
212
|
+
return { ...row(m), title: call.name === 'web_search' || call.name === 'search' ? 'Web search' : call.name, icon: _jsx(Globe, { size: 15, "aria-hidden": true }), detail: call.asked };
|
|
213
|
+
});
|
|
214
|
+
return [
|
|
215
|
+
{ id: 'outputs', title: 'Outputs', lead: { title: 'Create file or site', run: onCreate }, entries: made.map(row) },
|
|
216
|
+
{ id: 'sources', title: 'Sources', action: _jsx(Add, { at: at }), empty: 'Nothing yet', entries: [...asked, ...took.map(row)] },
|
|
217
|
+
];
|
|
218
|
+
}, [at, made, took, done, deck, ai, onCreate]);
|
|
255
219
|
}
|
|
256
220
|
/**
|
|
257
221
|
* The organization's sites, as an empty tab suggests them: `GET /v1/projects`,
|
|
@@ -267,7 +231,7 @@ export function useSites() {
|
|
|
267
231
|
if (stop.signal.aborted)
|
|
268
232
|
return;
|
|
269
233
|
const all = list(Array.isArray(body) ? body : body?.data);
|
|
270
|
-
setRows(all.filter((p) => typeof p.liveUrl === 'string' &&
|
|
234
|
+
setRows(all.filter((p) => typeof p.liveUrl === 'string' && p.liveUrl.startsWith('https://')).map((p) => ({ title: p.name || p.slug || 'Site', url: p.liveUrl })));
|
|
271
235
|
})
|
|
272
236
|
.catch(() => { });
|
|
273
237
|
return () => stop.abort();
|
package/dist/lib/host.d.ts
CHANGED
|
@@ -46,6 +46,11 @@ export declare const TABS = "https://tabs.hanzo.ai";
|
|
|
46
46
|
*/
|
|
47
47
|
export declare const CHAT = "/chat";
|
|
48
48
|
export declare const DEV = "/dev";
|
|
49
|
+
/**
|
|
50
|
+
* Studio: making images, audio, video and documents, and editing them.
|
|
51
|
+
* hanzo.ai/studio, whose page draws the app for a signed-in reader.
|
|
52
|
+
*/
|
|
53
|
+
export declare const STUDIO = "/studio";
|
|
49
54
|
/** Chat on a conversation, or /chat itself for a new one. */
|
|
50
55
|
export declare const talk: (id?: string | null) => string;
|
|
51
56
|
/** Dev at a builder address (`route` in @hanzo/build); '' is New, /dev. What is not an address is New. */
|
package/dist/lib/host.js
CHANGED
|
@@ -49,6 +49,11 @@ export const TABS = 'https://tabs.hanzo.ai';
|
|
|
49
49
|
*/
|
|
50
50
|
export const CHAT = '/chat';
|
|
51
51
|
export const DEV = '/dev';
|
|
52
|
+
/**
|
|
53
|
+
* Studio: making images, audio, video and documents, and editing them.
|
|
54
|
+
* hanzo.ai/studio, whose page draws the app for a signed-in reader.
|
|
55
|
+
*/
|
|
56
|
+
export const STUDIO = '/studio';
|
|
52
57
|
/** Chat on a conversation, or /chat itself for a new one. */
|
|
53
58
|
export const talk = (id) => (id ? `${CHAT}/${encodeURIComponent(id)}` : CHAT);
|
|
54
59
|
/** Dev at a builder address (`route` in @hanzo/build); '' is New, /dev. What is not an address is New. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/rooms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.65",
|
|
4
4
|
"description": "The workspace rooms — Home, Chat, Inbox, Contacts, Meet, Cal, Drive, Board, Work, Bots — and the frame that holds them, once, for every Hanzo surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@hanzo/ai": ">=0.6.23",
|
|
51
51
|
"@hanzo/appearance": ">=0.2.6",
|
|
52
|
-
"@hanzo/build": ">=0.2.
|
|
52
|
+
"@hanzo/build": ">=0.2.57",
|
|
53
53
|
"@hanzo/composer": ">=0.2.0",
|
|
54
54
|
"@hanzo/event": ">=0.3.56",
|
|
55
55
|
"@hanzo/gui": "^8.3.5",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@hanzo/ai": "0.6.23",
|
|
68
68
|
"@hanzo/appearance": "0.2.8",
|
|
69
|
-
"@hanzo/build": "0.2.
|
|
69
|
+
"@hanzo/build": "0.2.57",
|
|
70
70
|
"@hanzo/composer": "0.2.0",
|
|
71
71
|
"@hanzo/design": "0.5.34",
|
|
72
72
|
"@hanzo/event": "0.3.56",
|