@hanzo/app 0.2.1 → 0.2.3
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/App.js +1 -1
- package/dist/Chat.js +2 -2
- package/dist/Column.js +3 -3
- package/dist/Me.js +6 -2
- package/dist/Palette.js +5 -5
- package/dist/Settings.js +1 -0
- package/dist/SettingsPane.js +37 -1
- package/dist/Shell.js +7 -2
- package/dist/Top.js +1 -1
- package/dist/agents.d.ts +1 -0
- package/dist/agents.js +5 -4
- package/package.json +5 -4
package/dist/App.js
CHANGED
|
@@ -262,5 +262,5 @@ function Window({ bar }) {
|
|
|
262
262
|
};
|
|
263
263
|
return (_jsx(AiProvider, { client: client ?? undefined, children: _jsx(HostProvider, { host: host, children: _jsx(PrefsProvider, { children: _jsxs(YStack, { ref: windowRef, "data-slot": "window", ...(bar ? floor : null), flex: 1, minW: 0, height: "100dvh", overflow: "hidden", "$max-md": { position: 'fixed', t: TOP, l: 0, r: 0, height: HEIGHT, ...{ overflow: 'clip' } }, children: [bar ? (_jsxs(XStack, { "data-slot": "title-bar", height: BAR, shrink: 0, items: "center", gap: 2, pl: (bar.inset ?? 0) + 6, pr: "$2", ...bar.drag, children: [_jsx(XStack, { "$max-md": { display: 'none' }, children: _jsx(Toggle, { open: !closed, onPress: flip }) }), _jsx(XStack, { $md: { display: 'none' }, children: _jsx(Toggle, { open: drawer.state === 'open', onPress: drawer.open, label: t('Open sidebar') }) }), _jsx(Mark, { label: t('Back'), "data-slot": "back", onPress: () => router.back(), children: _jsx(ArrowLeft, { size: 18, "aria-hidden": true, "data-i18n-mirror": true }) }), _jsx(Mark, { label: t('Forward'), "data-slot": "forward", onPress: () => router.forward(), children: _jsx(ArrowRight, { size: 18, "aria-hidden": true, "data-i18n-mirror": true }) }), _jsx(XStack, { flex: 1, self: "stretch", ...bar.drag })] })) : null, _jsxs(XStack, { ref: drawer.pane, "data-room": "", "data-app": mode, "data-slot": "frame", ...(bar ? null : floor), ...(drawer.slide ? RAISED : null),
|
|
264
264
|
// inline-style: the slide, a transform with no logical form whose sign and distance the drawer writes on the element itself, a drag every frame (Drawer.tsx).
|
|
265
|
-
style: drawer.slide ?? undefined, flex: 1, minW: 0, minH: 0, paddingInlineEnd: "var(--pane-gap)", pb: "var(--pane-gap)", pt: bar ? 0 : 'var(--pane-gap)', "$max-md": { p: 0 }, children: [drawer.slide ? _jsx(Lift, {}) : null, _jsx(YStack, { height: "100%", "$max-md": { display: 'none' }, children: _jsx(Rail, { host: host, mode: mode, at: where, open: !closed, toggle: bar ? undefined : flip, onChat: toChat, onDev: toDev, onStudio: toStudio, onTabs: toTabs, go: move, onOrg: org }) }), closed || mode === 'tabs' ? null : (_jsx(YStack, { "$max-md": { display: 'none' }, children: _jsx(Column, { host: host, mode: mode, thread: thread, go: move, onShut: () => setClosed(true), onSeek: seek, onBack: back, places: sidebar }) })), _jsxs(YStack, { "data-slot": "stage", flex: 1, minW: 0, minH: 0, marginInlineStart: "var(--pane-gap)", "$max-md": { marginInlineStart: 0, pb: FOOT }, children: [bar ? null : _jsx(Top, { host: host, mode: mode, places: sidebar, go: move, onMenu: drawer.open, onChat: toChat, onDev: toDev }), _jsx(XStack, { "data-slot": "panes", flex: 1, minW: 0, minH: 0, children: mode === 'chat' ? (_jsx(Paned, { framed: true, children: _jsx(Chat, {}) })) : mode === 'tabs' ? (_jsx(YStack, { render: "main", "data-slot": "pane", ...pane(), overflow: "hidden", flex: 1, minW: 0, minH: 0, children: _jsx(Suspense, { fallback: null, children: _jsx(Terminals, {}) }) })) : mode === 'studio' ? (_jsx(YStack, { render: "main", "data-slot": "pane", ...pane(), overflow: "hidden", flex: 1, minW: 0, minH: 0, children: _jsx(YStack, { flex: 1, minH: 0, height: "100%", children: _jsx(Suspense, { fallback: null, children: _jsx(Studio, { host: maker, rail: false }) }) }) })) : (_jsx(YStack, { render: "main", "data-slot": "pane", ...(run ? null : { ...pane(), overflow: 'hidden' }), flex: 1, minW: 0, minH: 0, children: plans ? null : _jsx(Builder, { host: host, rail: false }) })) })] })] }), drawer.state === 'shut' ? null : (_jsx(Layer, { drawer: drawer, top: bar ? BAR : 0, children: _jsx(Column, { host: host, mode: mode, thread: thread, go: move, onShut: shut, onSeek: seek, onBack: back, drawer: true, places: sidebar, rail: _jsx(Rail, { host: host, mode: mode, at: where, open: true, rows: true, onChat: toChat, onDev: toDev, onStudio: toStudio, onTabs: toTabs, go: move, onOrg: org }), foot: _jsx(Foot, { host: host, onChat: fresh, onOrg: org }) }) })), finding ? _jsx(Palette, { go: move, onClose: found, mode: mode, host: host }) : null] }) }) }) }));
|
|
265
|
+
style: drawer.slide ?? undefined, flex: 1, minW: 0, minH: 0, paddingInlineStart: closed || mode === 'tabs' ? 'var(--pane-gap)' : 0, paddingInlineEnd: "var(--pane-gap)", pb: "var(--pane-gap)", pt: bar ? 0 : 'var(--pane-gap)', "$max-md": { p: 0 }, children: [drawer.slide ? _jsx(Lift, {}) : null, _jsx(YStack, { height: "100%", "$max-md": { display: 'none' }, children: _jsx(Rail, { host: host, mode: mode, at: where, open: !closed, toggle: bar ? undefined : flip, onChat: toChat, onDev: toDev, onStudio: toStudio, onTabs: toTabs, go: move, onOrg: org }) }), closed || mode === 'tabs' ? null : (_jsx(YStack, { "$max-md": { display: 'none' }, children: _jsx(Column, { host: host, mode: mode, thread: thread, go: move, onShut: () => setClosed(true), onSeek: seek, onBack: back, places: sidebar }) })), _jsxs(YStack, { "data-slot": "stage", flex: 1, minW: 0, minH: 0, marginInlineStart: "var(--pane-gap)", "$max-md": { marginInlineStart: 0, pb: FOOT }, children: [bar ? null : _jsx(Top, { host: host, mode: mode, places: sidebar, go: move, onMenu: drawer.open, onChat: toChat, onDev: toDev }), _jsx(XStack, { "data-slot": "panes", flex: 1, minW: 0, minH: 0, children: mode === 'chat' ? (_jsx(Paned, { framed: true, children: _jsx(Chat, {}) })) : mode === 'tabs' ? (_jsx(YStack, { render: "main", "data-slot": "pane", ...pane(), overflow: "hidden", flex: 1, minW: 0, minH: 0, children: _jsx(Suspense, { fallback: null, children: _jsx(Terminals, {}) }) })) : mode === 'studio' ? (_jsx(YStack, { render: "main", "data-slot": "pane", ...pane(), overflow: "hidden", flex: 1, minW: 0, minH: 0, children: _jsx(YStack, { flex: 1, minH: 0, height: "100%", children: _jsx(Suspense, { fallback: null, children: _jsx(Studio, { host: maker, rail: false }) }) }) })) : (_jsx(YStack, { render: "main", "data-slot": "pane", ...(run ? null : { ...pane(), overflow: 'hidden' }), flex: 1, minW: 0, minH: 0, children: plans ? null : _jsx(Builder, { host: host, rail: false }) })) })] })] }), drawer.state === 'shut' ? null : (_jsx(Layer, { drawer: drawer, top: bar ? BAR : 0, children: _jsx(Column, { host: host, mode: mode, thread: thread, go: move, onShut: shut, onSeek: seek, onBack: back, drawer: true, places: sidebar, rail: _jsx(Rail, { host: host, mode: mode, at: where, open: true, rows: true, onChat: toChat, onDev: toDev, onStudio: toStudio, onTabs: toTabs, go: move, onOrg: org }), foot: _jsx(Foot, { host: host, onChat: fresh, onOrg: org }) }) })), finding ? _jsx(Palette, { go: move, onClose: found, mode: mode, host: host }) : null] }) }) }) }));
|
|
266
266
|
}
|
package/dist/Chat.js
CHANGED
|
@@ -57,7 +57,7 @@ import { useHydrated } from "./lib/hydrated.js";
|
|
|
57
57
|
import { base, served } from "./lib/ai.js";
|
|
58
58
|
import { onServed } from "./lib/served.js";
|
|
59
59
|
import { refused as worded, speech, useDictation, useTalk, useVoice } from "@hanzo/voice";
|
|
60
|
-
import { Check, Clock, FileText, Image as ImageMark, Library as LibraryMark, Paperclip, X } from "lucide-react";
|
|
60
|
+
import { Check, Clock, FileText, Image as ImageMark, Library as LibraryMark, Paperclip, Sparkles, X } from "lucide-react";
|
|
61
61
|
import { FREE } from "./lib/ai.js";
|
|
62
62
|
import { openThread, useOpen } from "./open.js";
|
|
63
63
|
import { Beside, Framed } from "./Shell.js";
|
|
@@ -1480,7 +1480,7 @@ function Thread({ placeholder = message(), initial, anonymous = false, heading,
|
|
|
1480
1480
|
}, children: [_jsx(Schedule, { open: plan !== null, onOpenChange: (open) => {
|
|
1481
1481
|
if (!open)
|
|
1482
1482
|
setPlan(null);
|
|
1483
|
-
}, prompt: plan ?? "", model: model, models: models.map((m) => ({ id: m.id, name: nameOf(m.id, listed) })) }), 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: t("Drop files to attach") })] }) })) : null, _jsxs(XStack, { "data-slot": "conversation-head", height: 52, items: "center", justify: "space-between", gap: "$3", paddingInlineStart: "$4", paddingInlineEnd: "$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: tidy(mine.title) })) : null, room.length ? (_jsx(XStack, { role: "list", "aria-label": t("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", paddingInlineStart: "$1", paddingInlineEnd: "$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": t("Remove {name} from this chat", { name }), title: t("Remove {name}", { 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:
|
|
1483
|
+
}, prompt: plan ?? "", model: model, models: models.map((m) => ({ id: m.id, name: nameOf(m.id, listed) })) }), 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: t("Drop files to attach") })] }) })) : null, _jsxs(XStack, { "data-slot": "conversation-head", height: 52, items: "center", justify: "space-between", gap: "$3", paddingInlineStart: "$4", paddingInlineEnd: "$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: tidy(mine.title) })) : null, room.length ? (_jsx(XStack, { role: "list", "aria-label": t("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", paddingInlineStart: "$1", paddingInlineEnd: "$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": t("Remove {name} from this chat", { name }), title: t("Remove {name}", { 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: 4, shrink: 0, children: [free ? (_jsxs(Button, { size: "xs", variant: "outline", "data-slot": "header-upgrade", gap: "$1.5", px: "$2.5", py: "$1", rounded: "$4", cursor: "pointer", hoverStyle: { bg: 'var(--white-10)' }, onPress: () => setAsk({}), "aria-label": t("Upgrade"), children: [_jsx(Sparkles, { size: 13, color: "var(--primary)", "aria-hidden": true }), _jsx(Text, { fontSize: "$1", fontWeight: "600", color: "$ink", children: t("Upgrade") })] })) : null, open ? _jsx(Share, { thread: open }) : null, mine ? (_jsx(ConversationMenu, { threads: alone, active: open, onSchedule: anonymous ? undefined : () => setPlan(lastAsked()), children: _jsx(XStack, { children: _jsx(ThreadMore, { t: mine }) }) })) : null, _jsx(Summary, { sections: sections, onOpen: () => setPanel(true), label: t("Summary") }), _jsx(PanelToggle, { open: panel, onToggle: () => setPanel(!panel) })] })] }), wide && aside !== null ? (_jsx(Beside, { children: _jsx(Panel, { side: deck, kinds: NONE, onHide: () => setPanel(false), label: t("Tabs"), ...browsing }) })) : null, !wide && panel ? _jsx(Panel, { side: deck, kinds: NONE, sheet: true, onHide: () => setPanel(false), label: t("Tabs"), ...browsing }) : null, _jsx(ChatSurface, { ...chat, messages: shown, send: guarded,
|
|
1484
1484
|
// AN EMPTY ROOM CENTRES ITS COMPOSER on a laptop. While nothing has been
|
|
1485
1485
|
// said the opening (the heading) and the composer sit as one group in the
|
|
1486
1486
|
// middle of the height; the moment a turn exists the transcript takes the
|
package/dist/Column.js
CHANGED
|
@@ -100,12 +100,12 @@ export function Column({ host, mode, thread, go, onShut, onSeek, onBack, drawer
|
|
|
100
100
|
const scheduled = useScheduled(host, dev, at === 'scheduled');
|
|
101
101
|
const groups = places ??
|
|
102
102
|
(at === 'customize'
|
|
103
|
-
? tabs(host, dev)
|
|
103
|
+
? tabs(host, dev, t)
|
|
104
104
|
: at === 'library'
|
|
105
|
-
? library(host, dev)
|
|
105
|
+
? library(host, dev, t)
|
|
106
106
|
: at === 'scheduled'
|
|
107
107
|
? scheduled
|
|
108
|
-
: own(host, dev));
|
|
108
|
+
: own(host, dev, t));
|
|
109
109
|
const open = (row) => (row.kind === 'chat' ? go(talk(row.id)) : dev(row.id));
|
|
110
110
|
// Chat's New; Dev's is the first of its places.
|
|
111
111
|
const create = () => {
|
package/dist/Me.js
CHANGED
|
@@ -171,7 +171,8 @@ export function Me({ host, narrow = false, above = false, onOrg, }) {
|
|
|
171
171
|
// A personal plan is bought for the personal organization, beside any business one.
|
|
172
172
|
// The plans row's name (a phrase of `upgrade`'s).
|
|
173
173
|
const plans = upgrade(read.value?.label?.name);
|
|
174
|
-
const
|
|
174
|
+
const isFree = !read.value?.label?.name || read.value?.label?.name?.toLowerCase() === 'free';
|
|
175
|
+
const getPro = () => (personal ? window.location.assign(payUrl('/cart', { plan: 'pro', org: personal.name, returnUrl: window.location.href })) : window.location.assign(payUrl('/cart', { plan: 'pro', returnUrl: window.location.href })));
|
|
175
176
|
const apple = mac();
|
|
176
177
|
useEffect(() => {
|
|
177
178
|
if (above)
|
|
@@ -211,7 +212,10 @@ export function Me({ host, narrow = false, above = false, onOrg, }) {
|
|
|
211
212
|
row.current = el instanceof HTMLElement ? el : null;
|
|
212
213
|
}, render: "button", "data-slot": "me", "aria-label": t('Account: {name}', { name: [who, current].filter(Boolean).join(' · ') }), ...{ title: who }, width: narrow ? 36 : '100%', minH: narrow ? 36 : 48,
|
|
213
214
|
// A thumb's 44 on a touch screen.
|
|
214
|
-
$touchable: narrow ? { width: 44, minH: 44 } : undefined, px: narrow ? 0 : '$2', gap: "$2.5", rounded: narrow ? 999 : '$5', items: "center", justify: narrow ? 'center' : 'flex-start', hoverStyle: { bg: '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, cursor: "pointer", children: [_jsx(Face, { host: host, size: narrow ? 26 : 32 }), narrow ? null : (_jsxs(_Fragment, { children: [_jsxs(YStack, { flex: 1, minW: 0, children: [_jsx(SizableText, { size: "$3", fontWeight: "600", color: "$ink", numberOfLines: 1, text: "start", children: who }), working ? (_jsx(SizableText, { size: "$1", color: "$soft", numberOfLines: 1, text: "start", children: working })) : null] }),
|
|
215
|
+
$touchable: narrow ? { width: 44, minH: 44 } : undefined, px: narrow ? 0 : '$2', gap: "$2.5", rounded: narrow ? 999 : '$5', items: "center", justify: narrow ? 'center' : 'flex-start', hoverStyle: { bg: '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, cursor: "pointer", children: [_jsx(Face, { host: host, size: narrow ? 26 : 32 }), narrow ? null : (_jsxs(_Fragment, { children: [_jsxs(YStack, { flex: 1, minW: 0, children: [_jsx(SizableText, { size: "$3", fontWeight: "600", color: "$ink", numberOfLines: 1, text: "start", children: who }), working ? (_jsx(SizableText, { size: "$1", color: "$soft", numberOfLines: 1, text: "start", children: working })) : null] }), isFree ? (_jsx(Button, { size: "xs", variant: "outline", "data-slot": "me-upgrade", px: "$2", py: "$0.5", rounded: "$3", onPress: (e) => {
|
|
216
|
+
e?.stopPropagation?.();
|
|
217
|
+
getPro();
|
|
218
|
+
}, cursor: "pointer", children: t('Upgrade') })) : null, _jsx(ChevronsUpDown, { size: 14, "aria-hidden": true, opacity: 0.6 })] }))] }) }), _jsxs(DropdownMenuContent, { minW: 260, maxW: "calc(100vw - 16px)", "aria-labelledby": undefined, "aria-label": t('Account'), onCloseAutoFocus: back, children: [_jsxs(DropdownMenuSub, { open: account, onOpenChange: setAccount, children: [_jsxs(DropdownMenuSubTrigger, { minH: 48, gap: "$2.5", children: [_jsx(Face, { host: host, size: 28 }), _jsxs(YStack, { flex: 1, minW: 0, children: [_jsx(SizableText, { size: "$2", fontWeight: "600", color: "$ink", numberOfLines: 1, children: who }), _jsx(SizableText, { size: "$1", color: "$soft", numberOfLines: 1, children: host.person.email || working })] })] }), account ? (_jsxs(DropdownMenuSubContent, { minW: 260, maxW: "calc(100vw - 16px)", pointerEvents: "auto", children: [_jsx(Meter, { read: read, onPlans: () => leave('here'), onBilling: () => (setOpen(false), showSettings('billing')) }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { children: t('Organizations') }), all.map((o) => (_jsx(DropdownMenuItem, { onSelect: () => o.name !== current && onOrg(o.name), children: _jsx(Line, { icon: _jsx(Mark, { org: o }), sub: [o.personal ? t('Personal') : said(o.role, t), planFor(o)].filter(Boolean).join(' · '), trail: o.name === current ? _jsx(Check, { size: 16, "aria-label": t('Current') }) : null, children: o.display }) }, o.name))), _jsx(DropdownMenuItem, { onSelect: () => setCreating(true), children: _jsx(Line, { icon: _jsx(Plus, { size: 16, "aria-hidden": true }), children: t('Create organization') }) }), _jsx(DropdownMenuItem, { onSelect: () => out(site(settings('organization'))), children: _jsx(Line, { icon: _jsx(Settings, { size: 16, "aria-hidden": true }), children: t('Organization settings') }) }), where().team ? null : here && !here.personal ? (_jsx(DropdownMenuItem, { onSelect: () => out(`${ENTRY}&org=${encodeURIComponent(here.name)}`), children: _jsx(Line, { icon: _jsx(Users, { size: 16, "aria-hidden": true }), trail: _jsx(ArrowUpRight, { size: 14, "aria-hidden": true, opacity: 0.6 }), children: t('Open in Hanzo Team') }) })) : (_jsx(DropdownMenuItem, { onSelect: () => setCreating(true), children: _jsx(Line, { icon: _jsx(Users, { size: 16, "aria-hidden": true }), children: t('Create a team') }) })), superAdmin() ? (_jsx(DropdownMenuItem, { onSelect: choose, children: _jsx(Line, { icon: _jsx(Building2, { size: 16, "aria-hidden": true }), children: t('All organizations') }) })) : null] })) : null] }), team ? (_jsx(DropdownMenuItem, { "data-slot": "me-team", onSelect: () => team.name !== current && onOrg(team.name), children: _jsx(Line, { icon: _jsx(Mark, { org: team }), trail: team.name === current ? _jsx(Check, { size: 16, "aria-label": t('Current') }) : null, children: t('{org} · {plan}', { org: team.display, plan: teamPlan || t('No plan') }) }) })) : null, personal ? (_jsx(DropdownMenuItem, { "data-slot": "me-personal", onSelect: () => personal.name !== current && onOrg(personal.name), actionsVisibility: "always", actions: ownPlan ? undefined : (_jsx(Button, { size: "xs", variant: "outline", onPress: getPro, children: t('Get Pro') })), children: _jsx(Line, { icon: _jsx(CircleUserRound, { size: 16, "aria-hidden": true }), trail: personal.name === current ? _jsx(Check, { size: 16, "aria-label": t('Current') }) : null, children: t('Personal · {plan}', { plan: ownPlan || t('No plan') }) }) })) : null, _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { onSelect: () => leave('here'), children: _jsx(Line, { icon: _jsx(Sparkles, { size: 16, "aria-hidden": true }), children: t(plans) }) }), _jsx(DropdownMenuItem, { onSelect: () => showSettings('general'), children: _jsx(Line, { icon: _jsx(Palette, { size: 16, "aria-hidden": true }), children: t('Personalization') }) }), _jsx(DropdownMenuItem, { onSelect: () => showSettings('account'), children: _jsx(Line, { icon: _jsx(CircleUserRound, { size: 16, "aria-hidden": true }), children: t('Profile') }) }), _jsx(DropdownMenuItem, { "aria-keyshortcuts": "Control+, Meta+,", onSelect: () => showSettings('general'), children: _jsx(Line, { icon: _jsx(Settings, { size: 16, "aria-hidden": true }), trail: _jsx(DropdownMenuShortcut, { "aria-hidden": true, children: _jsx("bdi", { dir: "ltr", children: apple ? '⌘,' : 'Ctrl+,' }) }), children: t('Settings') }) }), _jsx(DropdownMenuItem, { onSelect: () => window.location.assign(site('/beta/status')), children: _jsx(Line, { icon: _jsx(FlaskConical, { size: 16, "aria-hidden": true }), children: t('Beta') }) }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuSub, { open: help, onOpenChange: setHelp, children: [_jsx(DropdownMenuSubTrigger, { children: _jsx(Line, { icon: _jsx(LifeBuoy, { size: 16, "aria-hidden": true }), children: t('Help') }) }), help ? (_jsxs(DropdownMenuSubContent, { minW: 240, maxW: "calc(100vw - 16px)", pointerEvents: "auto", children: [pages().map((p) => (_jsx(DropdownMenuItem, { onSelect: () => out(p.href), children: _jsx(Line, { icon: ICONS[p.key], trail: p.key === 'help' ? _jsx(ArrowUpRight, { size: 14, "aria-hidden": true, opacity: 0.6 }) : null, children: t(p.label) }) }, p.key))), _jsx(DropdownMenuItem, { "aria-keyshortcuts": "Control+/ Meta+/", onSelect: () => setKeys(true), children: _jsx(Line, { icon: _jsx(Keyboard, { size: 16, "aria-hidden": true }), trail: _jsx(DropdownMenuShortcut, { "aria-hidden": true, children: _jsx("bdi", { dir: "ltr", children: apple ? '⌘/' : 'Ctrl+/' }) }), children: t('Keyboard shortcuts') }) }), _jsx(DropdownMenuSeparator, {}), legal().map((p) => (_jsx(DropdownMenuItem, { onSelect: () => out(p.href), children: _jsx(Line, { icon: ICONS[p.key], children: t(p.label) }) }, p.key)))] })) : null] }), host.signOut ? (_jsx(DropdownMenuItem, { onSelect: () => host.signOut?.(), children: _jsx(Line, { icon: _jsx(LogOut, { size: 16, "aria-hidden": true, "data-i18n-mirror": true }), children: t('Log out') }) })) : null] })] }), _jsx(Create, { open: creating, onOpenChange: setCreating }), _jsx(Shortcuts, { open: keys, onOpenChange: setKeys, apple: apple })] }));
|
|
215
219
|
}
|
|
216
220
|
/** The app's keys (help.ts `KEYS`), one row each, spelled for this platform. */
|
|
217
221
|
function Shortcuts({ open, onOpenChange, apple }) {
|
package/dist/Palette.js
CHANGED
|
@@ -79,7 +79,7 @@ export function places(host, go, t = english) {
|
|
|
79
79
|
{ id: 'studio', label: 'Studio', icon: _jsx(WandSparkles, { ...ICON }), run: () => go(studio('')) },
|
|
80
80
|
{ id: 'tabs', label: 'Tabs', icon: _jsx(SquareTerminal, { ...ICON }), run: () => go(TERMINALS) },
|
|
81
81
|
...(host ? [{ id: 'team', label: 'Team', icon: _jsx(Users, { ...ICON }), keywords: ['workspace'], run: () => out(WORKSPACE) }] : []),
|
|
82
|
-
...(host ? rows(nav(host, builder).map((g) => ({ links: g.links.filter((l) => l.id !== NEW) })), '', 'dev') : []),
|
|
82
|
+
...(host ? rows(nav(host, builder, t).map((g) => ({ links: g.links.filter((l) => l.id !== NEW) })), '', 'dev') : []),
|
|
83
83
|
{ id: 'settings', label: t('Settings'), icon: _jsx(Settings, { ...ICON }), shortcut: ['Mod', ','], run: () => go(settings()) },
|
|
84
84
|
// The site's own pages, outside the app: the browser loads them.
|
|
85
85
|
{ id: 'referral', label: t('Referral'), icon: _jsx(Gift, { ...ICON }), keywords: ['invite', 'share'], run: () => window.location.assign(site('/referral')) },
|
|
@@ -92,9 +92,9 @@ export function places(host, go, t = english) {
|
|
|
92
92
|
const deep = [
|
|
93
93
|
...(host
|
|
94
94
|
? [
|
|
95
|
-
...rows(sections(host, builder).map((g) => ({ links: g.links.filter((l) => paged(l.id)) })), t('Settings'), 'settings'),
|
|
96
|
-
...rows(tabs(host, builder), t('Customize'), 'customize'),
|
|
97
|
-
...rows(library(host, builder).slice(1), t('Library'), 'library'),
|
|
95
|
+
...rows(sections(host, builder, t).map((g) => ({ links: g.links.filter((l) => paged(l.id)) })), t('Settings'), 'settings'),
|
|
96
|
+
...rows(tabs(host, builder, t), t('Customize'), 'customize'),
|
|
97
|
+
...rows(library(host, builder, t).slice(1), t('Library'), 'library'),
|
|
98
98
|
...rows(made(host, (p) => go(studio(p))), 'Studio', 'studio').filter((a) => a.id !== `studio-${NEW}`),
|
|
99
99
|
]
|
|
100
100
|
: []),
|
|
@@ -127,7 +127,7 @@ function tune(go) {
|
|
|
127
127
|
}
|
|
128
128
|
/** The palette's actions, named through `t`; a host that cannot do one (no theme to change, no org to pick) is not offered it. */
|
|
129
129
|
export function actions(host, go, signOut, keys, t = english) {
|
|
130
|
-
const upload = host ? library(host, (p) => go(app(p)))[0]?.links.find((l) => l.id === 'upload') : undefined;
|
|
130
|
+
const upload = host ? library(host, (p) => go(app(p)), t)[0]?.links.find((l) => l.id === 'upload') : undefined;
|
|
131
131
|
const list = [
|
|
132
132
|
{ id: 'new-chat', label: t('New chat'), icon: _jsx(SquarePen, { ...ICON }), run: () => (empty(), go(talk())) },
|
|
133
133
|
{ id: 'new-task', label: t('New Dev task'), icon: _jsx(Code2, { ...ICON }), keywords: ['run'], run: () => go(app('')) },
|
package/dist/Settings.js
CHANGED
|
@@ -39,6 +39,7 @@ const GROUPS = [
|
|
|
39
39
|
{ id: 'general', label: phrase('General') },
|
|
40
40
|
{ id: 'account', label: phrase('Account') },
|
|
41
41
|
{ id: 'billing', label: phrase('Billing') },
|
|
42
|
+
{ id: 'referrals', label: phrase('Referrals & Rewards') },
|
|
42
43
|
{ id: 'usage', label: phrase('Usage') },
|
|
43
44
|
{ id: 'capabilities', label: phrase('Capabilities'), note: phrase('What a model may reach for on your behalf.') },
|
|
44
45
|
{ id: 'privacy', label: phrase('Privacy'), href: site('/legal/privacy') },
|
package/dist/SettingsPane.js
CHANGED
|
@@ -6,7 +6,7 @@ import { useMemo, useState } from 'react';
|
|
|
6
6
|
import { phrase } from '@hanzo/i18n';
|
|
7
7
|
import { useI18n } from '@hanzo/i18n/react';
|
|
8
8
|
import { ArrowUpRight, ExternalLink } from 'lucide-react';
|
|
9
|
-
import { Box, Button, Separator, Text, XStack, YStack, } from '@hanzo/ui';
|
|
9
|
+
import { Box, Button, Input, Separator, Text, XStack, YStack, } from '@hanzo/ui';
|
|
10
10
|
import { tap } from './lib/tap.js';
|
|
11
11
|
import { useIam, useIamIdentity, useOrganizations } from '@hanzo/iam/react';
|
|
12
12
|
import { useSignOut } from './lib/signout.js';
|
|
@@ -52,6 +52,8 @@ function Pane({ id, note }) {
|
|
|
52
52
|
return _jsx(Account, {});
|
|
53
53
|
if (id === 'billing')
|
|
54
54
|
return _jsx(Billing, {});
|
|
55
|
+
if (id === 'referrals')
|
|
56
|
+
return _jsx(Referrals, {});
|
|
55
57
|
if (id === 'usage')
|
|
56
58
|
return _jsx(Usage, {});
|
|
57
59
|
if (id === 'model')
|
|
@@ -116,6 +118,40 @@ function Account() {
|
|
|
116
118
|
return (_jsx(Box, { render: _jsx("button", { type: "button" }), onClick: () => { pick(o.name); switchOrg(o.name); }, ...tap, children: _jsxs(XStack, { items: "center", justify: "space-between", py: "$2", width: "100%", gap: "$2", children: [_jsx(Text, { fontSize: "$3", color: here ? '$ink' : '$soft', children: o.displayName || o.name }), here && currentRole ? _jsx(Text, { fontSize: "$2", color: "$soft", children: currentRole }) : null] }) }, o.name));
|
|
117
119
|
}))] }), _jsx(Separator, {}), _jsx(XStack, { children: _jsx(Button, { size: "sm", onClick: () => logout(), children: t('Sign out') }) })] }));
|
|
118
120
|
}
|
|
121
|
+
/** Referrals & Rewards — customer referral program and affiliate partner portal. */
|
|
122
|
+
function Referrals() {
|
|
123
|
+
const { t } = useI18n();
|
|
124
|
+
const identity = useIamIdentity();
|
|
125
|
+
const { isAuthenticated } = useIam();
|
|
126
|
+
const [copied, setCopied] = useState(false);
|
|
127
|
+
const [vanity, setVanity] = useState('');
|
|
128
|
+
const [applied, setApplied] = useState(false);
|
|
129
|
+
if (!isAuthenticated || !identity) {
|
|
130
|
+
return _jsx(Text, { fontSize: "$3", color: "$soft", children: t('Sign in to view your referral program.') });
|
|
131
|
+
}
|
|
132
|
+
const handle = identity.name ? identity.name.toLowerCase().replace(/\s+/g, '-') : (identity.email ? identity.email.split('@')[0] : 'user');
|
|
133
|
+
const referralUrl = `https://hanzo.ai/?ref=${encodeURIComponent(handle)}`;
|
|
134
|
+
const copy = () => {
|
|
135
|
+
navigator.clipboard.writeText(referralUrl);
|
|
136
|
+
setCopied(true);
|
|
137
|
+
setTimeout(() => setCopied(false), 2000);
|
|
138
|
+
};
|
|
139
|
+
const tweet = () => {
|
|
140
|
+
const text = 'Deploy AI agents, sites, and apps on @HanzoAI. Get $20 in free cloud compute credits:';
|
|
141
|
+
window.open(`https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${encodeURIComponent(referralUrl)}`, '_blank', 'noopener,noreferrer');
|
|
142
|
+
};
|
|
143
|
+
const linkedin = () => {
|
|
144
|
+
window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(referralUrl)}`, '_blank', 'noopener,noreferrer');
|
|
145
|
+
};
|
|
146
|
+
const telegram = () => {
|
|
147
|
+
window.open(`https://t.me/share/url?url=${encodeURIComponent(referralUrl)}&text=${encodeURIComponent('Get $20 free Hanzo cloud compute credits:')}`, '_blank', 'noopener,noreferrer');
|
|
148
|
+
};
|
|
149
|
+
const whatsapp = () => {
|
|
150
|
+
window.open(`https://api.whatsapp.com/send?text=${encodeURIComponent('Deploy with Hanzo — get $20 in free cloud credits: ' + referralUrl)}`, '_blank', 'noopener,noreferrer');
|
|
151
|
+
};
|
|
152
|
+
return (_jsxs(YStack, { gap: "$5", maxW: 640, children: [_jsxs(YStack, { gap: "$1.5", children: [_jsx(XStack, { items: "center", gap: "$2", children: _jsx(Text, { fontSize: "$4", fontWeight: "600", color: "$ink", children: t('Give $20, Get 20%') }) }), _jsx(Text, { fontSize: "$3", color: "$soft", children: t('Invite developers, creators, and colleagues to Hanzo. They get $20 in free cloud compute credits, and you earn 20% recurring revenue share on their compute spend for 12 months.') })] }), _jsxs(YStack, { gap: "$2", p: "$3", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", children: [_jsx(Text, { fontSize: "$2", fontWeight: "600", color: "$ink", children: t('Your Personal Referral Link') }), _jsxs(XStack, { items: "center", gap: "$2", children: [_jsx(Box, { flex: 1, p: "$2", rounded: "$2", bg: "$hover", borderWidth: 1, borderColor: "$borderColor", children: _jsx(Text, { fontSize: "$2", color: "$ink", fontFamily: "$mono", numberOfLines: 1, children: referralUrl }) }), _jsx(Button, { size: "sm", onClick: copy, children: copied ? t('Copied!') : t('Copy Link') })] }), _jsxs(XStack, { items: "center", justify: "space-between", pt: "$2", flexWrap: "wrap", gap: "$2", children: [_jsx(Text, { fontSize: "$1", color: "$soft", children: t('1-Click Social Share:') }), _jsxs(XStack, { gap: "$2", flexWrap: "wrap", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: tweet, children: "\uD835\uDD4F (Twitter)" }), _jsx(Button, { size: "sm", variant: "outline", onClick: linkedin, children: "LinkedIn" }), _jsx(Button, { size: "sm", variant: "outline", onClick: telegram, children: "Telegram" }), _jsx(Button, { size: "sm", variant: "outline", onClick: whatsapp, children: "WhatsApp" })] })] })] }), _jsx(Separator, {}), _jsxs(YStack, { gap: "$2", children: [_jsx(Text, { fontSize: "$3", fontWeight: "600", color: "$ink", children: t('Referral Rules & Offer Details') }), _jsxs(YStack, { gap: "$1", children: [_jsxs(Text, { fontSize: "$2", color: "$soft", children: ["\u2022 ", t('30-day attribution window: First click binds to user identity upon registration.')] }), _jsxs(Text, { fontSize: "$2", color: "$soft", children: ["\u2022 ", t('20% recurring margin share: Calculated against net platform margin (safe from wholesale token dilution).')] }), _jsxs(Text, { fontSize: "$2", color: "$soft", children: ["\u2022 ", t('Payout options: Platform credits, direct wire/ACH, or on-chain EVM wallet settlement.')] })] })] }), _jsx(Separator, {}), _jsxs(YStack, { gap: "$3", children: [_jsx(Text, { fontSize: "$3", fontWeight: "600", color: "$ink", children: t('Official Affiliate & Creator Program') }), _jsx(Text, { fontSize: "$2", color: "$soft", children: t('Building an open-source project, template, or dev community? Apply for official affiliate status for custom vanity links (hanzo.ai/?aff=code) and elevated commission tiers.') }), !applied ? (_jsxs(XStack, { gap: "$2", children: [_jsx(Input, { flex: 1, size: "sm", placeholder: t('Desired vanity code (e.g. your project)'), value: vanity, onChange: (e) => setVanity(e.target.value) }), _jsx(Button, { size: "sm", onClick: () => { if (vanity.trim())
|
|
153
|
+
setApplied(true); }, children: t('Apply for Partner') })] })) : (_jsx(Box, { p: "$3", rounded: "$2", bg: "$hover", children: _jsx(Text, { fontSize: "$2", color: "$ink", children: t('Application submitted for review. Manage payouts and advanced settings in platform.hanzo.ai/dashboard/settings/referrals') }) })), _jsx(XStack, { pt: "$1", children: _jsx(Box, { render: _jsx("a", { href: "https://platform.hanzo.ai/dashboard/settings/referrals", target: "_blank", rel: "noreferrer" }), ...tap, children: _jsxs(XStack, { items: "center", gap: "$1.5", children: [_jsx(Text, { fontSize: "$2", color: "$ink", children: t('Open Full Referrals & Affiliate Portal') }), _jsx(ArrowUpRight, { size: 13, "aria-hidden": true })] }) }) })] })] }));
|
|
154
|
+
}
|
|
119
155
|
/** Where the plan's and billing's reads go: this browser's bearer, in its organization. */
|
|
120
156
|
function useTarget() {
|
|
121
157
|
const scoped = org();
|
package/dist/Shell.js
CHANGED
|
@@ -17,7 +17,7 @@ import { createContext, lazy, Suspense, useCallback, useContext, useEffect, useM
|
|
|
17
17
|
import { createPortal } from "react-dom";
|
|
18
18
|
import { phrase } from "@hanzo/i18n";
|
|
19
19
|
import { useI18n } from "@hanzo/i18n/react";
|
|
20
|
-
import { MessageSquare, Code2, Inbox, Bot, ListChecks, HardDrive, Settings2, UserPlus, PanelLeftClose, Search, Hash, AtSign, Lock, Workflow, Plus, ArrowLeft, ArrowRight, Send, Minus, Blocks, Star, FolderOpen, Activity, BookOpen, SquareTerminal, Share2, PanelLeft, PanelRight, Users, Globe, Cpu, Boxes, Wallet, Video, Calendar, LayoutGrid, ArrowUpLeft, } from "lucide-react";
|
|
20
|
+
import { MessageSquare, Code2, Inbox, Bot, ListChecks, HardDrive, Settings2, UserPlus, PanelLeftClose, Search, Hash, AtSign, Lock, Workflow, Plus, ArrowLeft, ArrowRight, Send, Minus, Blocks, Star, FolderOpen, Activity, BookOpen, SquareTerminal, Share2, PanelLeft, PanelRight, Users, Globe, Cpu, Boxes, Wallet, Video, Calendar, LayoutGrid, ArrowUpLeft, Sparkles, } from "lucide-react";
|
|
21
21
|
import { AiProvider, useAgents, useInbox, useModels, usePeople, } from "@hanzo/ai/react";
|
|
22
22
|
import { PINNED } from "./recent.js";
|
|
23
23
|
import { ConversationMenu, ThreadRow, useThreadList } from "./thread.js";
|
|
@@ -48,6 +48,8 @@ import { mark } from "./lib/mark.js";
|
|
|
48
48
|
import { useOpen } from "./open.js";
|
|
49
49
|
import { useSpan } from "./span.js";
|
|
50
50
|
import { pane } from "./ground.js";
|
|
51
|
+
import { useFree } from "./Upgrade.js";
|
|
52
|
+
import { payUrl } from "./lib/pay.js";
|
|
51
53
|
/** The new-agent row's fields: an outlined box in the room's own ink. */
|
|
52
54
|
const FIELD = {
|
|
53
55
|
bg: "transparent",
|
|
@@ -385,6 +387,7 @@ function Chats({ filter = "", onPick, }) {
|
|
|
385
387
|
const { isAuthenticated, user } = useIam();
|
|
386
388
|
const { user: account } = useAccount();
|
|
387
389
|
const signedIn = isAuthenticated || Boolean(user) || Boolean(account) || hasSession();
|
|
390
|
+
const free = useFree(signedIn);
|
|
388
391
|
const mergedThreads = useMemo(() => {
|
|
389
392
|
const list = threads.map((t) => ({
|
|
390
393
|
id: t.id,
|
|
@@ -562,6 +565,7 @@ function Team({ filter = "", onPick, navigate, }) {
|
|
|
562
565
|
const { isAuthenticated, user } = useIam();
|
|
563
566
|
const { user: account } = useAccount();
|
|
564
567
|
const signedIn = isAuthenticated || Boolean(user) || Boolean(account) || hasSession();
|
|
568
|
+
const free = useFree(signedIn);
|
|
565
569
|
const [starred] = useStarred();
|
|
566
570
|
const shown = list(rooms).filter((r) => matches(r.name, filter));
|
|
567
571
|
const favourites = shown.filter((r) => starred.has(titleOf(r.name, r.direct)));
|
|
@@ -1216,6 +1220,7 @@ function Frame({ mode, children, navigate, back, forward, }) {
|
|
|
1216
1220
|
const settled = hydrated && !isLoading;
|
|
1217
1221
|
const { user: account } = useAccount();
|
|
1218
1222
|
const signedIn = isAuthenticated || Boolean(user) || Boolean(account) || hasSession();
|
|
1223
|
+
const free = useFree(signedIn);
|
|
1219
1224
|
const logout = useSignOut();
|
|
1220
1225
|
const face = account?.avatar ?? user?.avatar;
|
|
1221
1226
|
// The account menu's reading of this host: who, in which organization, and how they leave.
|
|
@@ -1260,7 +1265,7 @@ function Frame({ mode, children, navigate, back, forward, }) {
|
|
|
1260
1265
|
gridTemplateColumns: "minmax(0, 1fr)",
|
|
1261
1266
|
gridTemplateRows: `44px minmax(0, 1fr) ${TABS_HEIGHT}`,
|
|
1262
1267
|
gridTemplateAreas: '"bar" "pane" "rail"',
|
|
1263
|
-
}, position: "relative", width: "100%", height: "100dvh", overflow: "hidden", bg: "$background", backgroundImage: "var(--pane-ground)", children: [_jsx(Rail, { mode: mode, places: places, open: asked, team: onApex ? (signedIn ? ENTRY : WORKSPACE) : undefined, navigate: navigate, onSettings: () => showSettings(FIRST), onMore: () => setFinding(true) }), _jsxs(XStack, { render: "header", "data-slot": "bar", gridArea: "bar", ...sheet(0), height: 44, shrink: 0, items: "center", px: "$3", gap: "$3", borderBottomWidth: 1, borderColor: "var(--edge, var(--white-06))", children: [_jsxs(XStack, { items: "center", gap: "$1", shrink: 0, children: [_jsx(SidebarIconButton, { ...TAP, label: t(shown ? "Close sidebar" : "Open sidebar"), onPress: toggle, onMouseEnter: () => setPeeking(true), children: _jsx(PanelLeft, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) }), back || forward ? (_jsxs(XStack, { display: "none", $md: { display: "flex" }, items: "center", gap: "$1", shrink: 0, children: [_jsx(SidebarIconButton, { ...TAP, label: t("Back"), onPress: () => back?.(), children: _jsx(ArrowLeft, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) }), _jsx(SidebarIconButton, { ...TAP, label: t("Forward"), onPress: () => forward?.(), children: _jsx(ArrowRight, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) })] })) : null] }), _jsx(XStack, { flex: 1, justify: "center", children: _jsx(YStack, { width: 440, maxW: "100%", position: "relative", children: _jsxs(Box, { render: "button", onClick: () => setFinding(true), display: "flex", flexDirection: "row", "data-slot": "find", items: "center", "$max-md": { justify: "center" }, gap: "$2", width: "100%", height: CONTROL, px: "$2.5", rounded: "$2", borderWidth: 1, borderColor: "$borderColor", hoverStyle: { bg: '$hover' }, children: [_jsx(Search, { size: 13, "aria-hidden": true, color: "var(--soft, var(--muted-foreground))" }), _jsx(Text, { fontSize: "$1", color: "$soft", "$max-md": { display: "none" }, children: t("Search {workspace}", { workspace }) }), _jsx(Shortcut, { keys: ["Mod", "K"], marginInlineStart: "auto", "data-i18n-ltr": "", "$max-md": { display: "none" } })] }) }) }), _jsxs(XStack, { shrink: 0, minW: 0, justify: "flex-end", items: "center", gap: "$2", children: [settled && !signedIn ? (_jsx(Box, { ...TAP, render: "button", onClick: () => enter(LOGIN), display: "flex", items: "center", justify: "center", cursor: "pointer", children: _jsx(XStack, { items: "center", justify: "center", height: CONTROL, px: "$2.5", rounded: "$2", borderWidth: 1, borderColor: "$borderColor", hoverStyle: { bg: '$hover' }, children: _jsx(Text, { fontSize: "$1", fontWeight: "600", color: "$ink", children: t("Sign in") }) }) })) : null, _jsxs(XStack, { display: "none", $lg: { display: "flex" }, items: "center", gap: "$1", children: [_jsx(SidebarIconButton, { ...TAP, label: t(aside === "roster" ? "Hide directory & roster" : "Show directory & roster"), onPress: () => showAside(aside === "roster" ? null : "roster"), children: _jsx(Users, { size: 16, "aria-hidden": true }) }), _jsx(SidebarIconButton, { ...TAP, label: t(aside === "tasks" ? "Close side panel" : "Open side panel"), onPress: () => showAside(aside === "tasks" ? null : "tasks"), children: _jsx(PanelRight, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) })] })] })] }), shown ? (_jsx(Box, { render: "button", "aria-label": t("Close sidebar"), onClick: dismiss, ...scrim, "data-slot": "scrim", position: "absolute", t: 44, r: 0, b: TABS_HEIGHT, l: 0, z: "var(--z-scrim)", $md: { display: "none" } })) : null, shown ? (_jsx(XStack, { "data-slot": "list", gridArea: "list", position: asked ? "relative" : "absolute", ...(asked ? {} : { top: 44, bottom: 0, insetInlineStart: 64 }), "$max-md": { position: "fixed", t: 44, r: 0, b: TABS_HEIGHT, l: 0, width: "100%" }, z: "var(--z-drawer)", bg: "$background", onMouseEnter: () => setPeeking(true), onMouseLeave: () => {
|
|
1268
|
+
}, position: "relative", width: "100%", height: "100dvh", overflow: "hidden", bg: "$background", backgroundImage: "var(--pane-ground)", children: [_jsx(Rail, { mode: mode, places: places, open: asked, team: onApex ? (signedIn ? ENTRY : WORKSPACE) : undefined, navigate: navigate, onSettings: () => showSettings(FIRST), onMore: () => setFinding(true) }), _jsxs(XStack, { render: "header", "data-slot": "bar", gridArea: "bar", ...sheet(0), height: 44, shrink: 0, items: "center", px: "$3", gap: "$3", borderBottomWidth: 1, borderColor: "var(--edge, var(--white-06))", children: [_jsxs(XStack, { items: "center", gap: "$1", shrink: 0, children: [_jsx(SidebarIconButton, { ...TAP, label: t(shown ? "Close sidebar" : "Open sidebar"), onPress: toggle, onMouseEnter: () => setPeeking(true), children: _jsx(PanelLeft, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) }), back || forward ? (_jsxs(XStack, { display: "none", $md: { display: "flex" }, items: "center", gap: "$1", shrink: 0, children: [_jsx(SidebarIconButton, { ...TAP, label: t("Back"), onPress: () => back?.(), children: _jsx(ArrowLeft, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) }), _jsx(SidebarIconButton, { ...TAP, label: t("Forward"), onPress: () => forward?.(), children: _jsx(ArrowRight, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) })] })) : null] }), _jsx(XStack, { flex: 1, justify: "center", children: _jsx(YStack, { width: 440, maxW: "100%", position: "relative", children: _jsxs(Box, { render: "button", onClick: () => setFinding(true), display: "flex", flexDirection: "row", "data-slot": "find", items: "center", "$max-md": { justify: "center" }, gap: "$2", width: "100%", height: CONTROL, px: "$2.5", rounded: "$2", borderWidth: 1, borderColor: "$borderColor", hoverStyle: { bg: '$hover' }, children: [_jsx(Search, { size: 13, "aria-hidden": true, color: "var(--soft, var(--muted-foreground))" }), _jsx(Text, { fontSize: "$1", color: "$soft", "$max-md": { display: "none" }, children: t("Search {workspace}", { workspace }) }), _jsx(Shortcut, { keys: ["Mod", "K"], marginInlineStart: "auto", "data-i18n-ltr": "", "$max-md": { display: "none" } })] }) }) }), _jsxs(XStack, { shrink: 0, minW: 0, justify: "flex-end", items: "center", gap: "$2", children: [settled && !signedIn ? (_jsx(Box, { ...TAP, render: "button", onClick: () => enter(LOGIN), display: "flex", items: "center", justify: "center", cursor: "pointer", children: _jsx(XStack, { items: "center", justify: "center", height: CONTROL, px: "$2.5", rounded: "$2", borderWidth: 1, borderColor: "$borderColor", hoverStyle: { bg: '$hover' }, children: _jsx(Text, { fontSize: "$1", fontWeight: "600", color: "$ink", children: t("Sign in") }) }) })) : null, settled && signedIn && free ? (_jsx(Box, { ...TAP, render: "button", onClick: () => window.location.assign(payUrl("/cart", { plan: "pro", returnUrl: window.location.href })), display: "flex", items: "center", justify: "center", cursor: "pointer", "aria-label": t("Upgrade"), "data-slot": "bar-upgrade", children: _jsxs(XStack, { items: "center", justify: "center", height: CONTROL, px: "$2.5", rounded: "$2", borderWidth: 1, borderColor: "$borderColor", gap: "$1.5", hoverStyle: { bg: "$hover" }, children: [_jsx(Sparkles, { size: 13, "aria-hidden": true, color: "var(--primary)" }), _jsx(Text, { fontSize: "$1", fontWeight: "600", color: "$ink", children: t("Upgrade") })] }) })) : null, _jsxs(XStack, { display: "none", $lg: { display: "flex" }, items: "center", gap: "$1", children: [_jsx(SidebarIconButton, { ...TAP, label: t(aside === "roster" ? "Hide directory & roster" : "Show directory & roster"), onPress: () => showAside(aside === "roster" ? null : "roster"), children: _jsx(Users, { size: 16, "aria-hidden": true }) }), _jsx(SidebarIconButton, { ...TAP, label: t(aside === "tasks" ? "Close side panel" : "Open side panel"), onPress: () => showAside(aside === "tasks" ? null : "tasks"), children: _jsx(PanelRight, { size: 16, "aria-hidden": true, "data-i18n-mirror": "" }) })] })] })] }), shown ? (_jsx(Box, { render: "button", "aria-label": t("Close sidebar"), onClick: dismiss, ...scrim, "data-slot": "scrim", position: "absolute", t: 44, r: 0, b: TABS_HEIGHT, l: 0, z: "var(--z-scrim)", $md: { display: "none" } })) : null, shown ? (_jsx(XStack, { "data-slot": "list", gridArea: "list", position: asked ? "relative" : "absolute", ...(asked ? {} : { top: 44, bottom: 0, insetInlineStart: 64 }), "$max-md": { position: "fixed", t: 44, r: 0, b: TABS_HEIGHT, l: 0, width: "100%" }, z: "var(--z-drawer)", bg: "$background", onMouseEnter: () => setPeeking(true), onMouseLeave: () => {
|
|
1264
1269
|
if (!asked)
|
|
1265
1270
|
setPeeking(false);
|
|
1266
1271
|
}, children: list })) : null, _jsx(Paned, { swap: settingsPane ? _jsx(Suspense, { fallback: null, children: _jsx(SettingsPane, { id: settingsPane }) }) : undefined, children: children }), finding ? (_jsx(Palette, { actions: doors, onClose: found,
|
package/dist/Top.js
CHANGED
|
@@ -47,7 +47,7 @@ function Side({ value, children }) {
|
|
|
47
47
|
}
|
|
48
48
|
export function Top({ host, mode, places, go, onMenu, onChat, onDev, }) {
|
|
49
49
|
const { t } = useI18n();
|
|
50
|
-
const made = mode === 'chat' ? null : (places ?? nav(host, (p) => host.go(p))).flatMap((g) => g.links).find((l) => l.id === NEW);
|
|
50
|
+
const made = mode === 'chat' ? null : (places ?? nav(host, (p) => host.go(p), t)).flatMap((g) => g.links).find((l) => l.id === NEW);
|
|
51
51
|
const fresh = mode === 'chat'
|
|
52
52
|
? {
|
|
53
53
|
label: t('New chat'),
|
package/dist/agents.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare const MEMOJI = "memoji style 3D emoji portrait, head and shoulder
|
|
|
12
12
|
* The default agents an org adds in one press (Customize › Agents, @hanzo/build
|
|
13
13
|
* `hire`): the core team, each as its persona writes it, then QA, Ops and
|
|
14
14
|
* Support. An org starts with none of them and loads none until it adds them.
|
|
15
|
+
* Browse lists them under Team, by the name each goes by.
|
|
15
16
|
*/
|
|
16
17
|
export declare const CAST: NonNullable<Host['cast']>;
|
|
17
18
|
/**
|
package/dist/agents.js
CHANGED
|
@@ -14,12 +14,13 @@ export const MEMOJI = 'memoji style 3D emoji portrait, head and shoulders, cente
|
|
|
14
14
|
* The default agents an org adds in one press (Customize › Agents, @hanzo/build
|
|
15
15
|
* `hire`): the core team, each as its persona writes it, then QA, Ops and
|
|
16
16
|
* Support. An org starts with none of them and loads none until it adds them.
|
|
17
|
+
* Browse lists them under Team, by the name each goes by.
|
|
17
18
|
*/
|
|
18
19
|
export const CAST = [
|
|
19
|
-
...TEAM.map((one) => ({ name: one.id, description: `${one.name} — ${one.role}`, model: one.model, instructions: one.instructions, avatar: `/agents/${one.id}.png` })),
|
|
20
|
-
{ name: 'qa', description: 'QA — Automated Testing & Verification', model: 'enso-auto', instructions: '' },
|
|
21
|
-
{ name: 'ops', description: 'Ops — Site Reliability & Cloud Infrastructure', model: 'enso-auto', instructions: '' },
|
|
22
|
-
{ name: 'support', description: 'Support — Customer Support & Triage Specialist', model: 'enso-auto', instructions: '' },
|
|
20
|
+
...TEAM.map((one) => ({ name: one.id, title: one.name, category: 'Team', description: `${one.name} — ${one.role}`, model: one.model, instructions: one.instructions, avatar: `/agents/${one.id}.png` })),
|
|
21
|
+
{ name: 'qa', title: 'QA', category: 'Team', description: 'QA — Automated Testing & Verification', model: 'enso-auto', instructions: '' },
|
|
22
|
+
{ name: 'ops', title: 'Ops', category: 'Team', description: 'Ops — Site Reliability & Cloud Infrastructure', model: 'enso-auto', instructions: '' },
|
|
23
|
+
{ name: 'support', title: 'Support', category: 'Team', description: 'Support — Customer Support & Triage Specialist', model: 'enso-auto', instructions: '' },
|
|
23
24
|
];
|
|
24
25
|
const RANK = new Map(TEAM.map((one, i) => [one.id, i]));
|
|
25
26
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/app",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Hanzo's app: the shell and its apps (Home, Chat, Inbox, Contacts, Meet, Calendar, Drive, Board, Work, Bots), 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.81",
|
|
53
53
|
"@hanzo/composer": ">=0.2.0",
|
|
54
54
|
"@hanzo/event": ">=0.3.56",
|
|
55
55
|
"@hanzo/gui": "^8.3.5",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@hanzo/ai": "0.6.23",
|
|
71
71
|
"@hanzo/appearance": "0.2.8",
|
|
72
|
-
"@hanzo/build": "0.2.
|
|
72
|
+
"@hanzo/build": "0.2.81",
|
|
73
73
|
"@hanzo/composer": "0.2.0",
|
|
74
74
|
"@hanzo/design": "0.5.34",
|
|
75
75
|
"@hanzo/event": "0.3.56",
|
|
@@ -100,7 +100,8 @@
|
|
|
100
100
|
},
|
|
101
101
|
"repository": {
|
|
102
102
|
"type": "git",
|
|
103
|
-
"url": "git+https://github.com/hanzoai/app.git"
|
|
103
|
+
"url": "git+https://github.com/hanzoai/app.git",
|
|
104
|
+
"directory": "pkg/app"
|
|
104
105
|
},
|
|
105
106
|
"engines": {
|
|
106
107
|
"node": ">=22.18"
|