@hanzo/rooms 0.1.43 → 0.1.45
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.d.ts +1 -0
- package/dist/App.js +87 -0
- package/dist/Settings.js +1 -7
- package/package.json +1 -1
package/dist/App.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function App(): import("react").JSX.Element;
|
package/dist/App.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// The web app as the whole window, in two modes: Chat, a conversation with the
|
|
4
|
+
// product's AI, and Dev, @hanzo/build's `<Builder>` without a rail of its own.
|
|
5
|
+
// One column serves both (Column.tsx): the wordmark and the switch, New, Dev's
|
|
6
|
+
// places, the reader's Recents in both modes, and the account. The address says
|
|
7
|
+
// the mode, as a path (lib/host `talk`, `app`, `place`): `/` and `/chat` are
|
|
8
|
+
// Chat on a new conversation, `/chat/<id>` one of the reader's, and a path under
|
|
9
|
+
// `/dev` is Dev: `/dev/run/<id>` a run, `/dev/projects/<org>/<repo>` a project.
|
|
10
|
+
// Moving between the modes is a history entry (`go`), never a load, so a host
|
|
11
|
+
// serves this one component for every path under each.
|
|
12
|
+
//
|
|
13
|
+
// Every host draws this: hanzo.ai at `/`, the desktop app as its main window.
|
|
14
|
+
// The host mounts IamProvider and `<Rooms>` with its router and the path, and
|
|
15
|
+
// draws this only for a signed-in reader; what a stranger sees is the host's.
|
|
16
|
+
//
|
|
17
|
+
// DEV'S PANE HAS NO COLUMN BESIDE IT. The column beside a pane is Chat's (its
|
|
18
|
+
// pinned summary, `useOpen().aside`), and that choice outlives a move to Dev,
|
|
19
|
+
// where nothing fills it: drawn there it was an empty pane to the right of the
|
|
20
|
+
// builder. So Dev's pane is cut on its own and the summary is Chat's alone.
|
|
21
|
+
//
|
|
22
|
+
// THE WINDOW IS A FRAME (`data-slot="frame"`): the column, the pane and the
|
|
23
|
+
// column beside it are three panes floating on a lit floor (ground.ts), one
|
|
24
|
+
// gutter round them and between them, `--pane-gap`, each sized by the edge
|
|
25
|
+
// beside it.
|
|
26
|
+
import { useEffect, useState } from 'react';
|
|
27
|
+
import { Menu } from 'lucide-react';
|
|
28
|
+
import { AiProvider } from '@hanzo/ai/react';
|
|
29
|
+
import { Text, XStack, YStack } from '@hanzo/gui';
|
|
30
|
+
import { Builder, HostProvider, route } from '@hanzo/build';
|
|
31
|
+
import { SidebarIconButton } from '@hanzo/ui/chat';
|
|
32
|
+
import { scrim } from '@hanzo/ui/glass';
|
|
33
|
+
import { useAi } from './lib/ai.js';
|
|
34
|
+
import { Chat } from './Chat.js';
|
|
35
|
+
import { Column } from './Column.js';
|
|
36
|
+
import { useDevHost } from './dev.js';
|
|
37
|
+
import { useRooms } from './host.js';
|
|
38
|
+
import { wordmark } from './ModeMark.js';
|
|
39
|
+
import { empty, openThread, useOpen } from './open.js';
|
|
40
|
+
import { Paned } from './Shell.js';
|
|
41
|
+
import { floor, pane } from './ground.js';
|
|
42
|
+
import { app, go, place, talk } from './lib/host.js';
|
|
43
|
+
/** `/` is Chat on a new conversation. */
|
|
44
|
+
const HOME = { mode: 'chat', thread: null };
|
|
45
|
+
/** Where each mode was last, so the switch goes back to it. */
|
|
46
|
+
const last = { chat: '', dev: '' };
|
|
47
|
+
export function App() {
|
|
48
|
+
const host = useDevHost();
|
|
49
|
+
const { client } = useAi();
|
|
50
|
+
const here = useRooms().path ?? '/';
|
|
51
|
+
const at = place(here) ?? HOME;
|
|
52
|
+
const mode = at.mode;
|
|
53
|
+
// A run floats two panes of its own, so the pane it stands in is not cut.
|
|
54
|
+
const run = at.mode === 'dev' && route(at.at).kind === 'run';
|
|
55
|
+
const asked = at.mode === 'chat' ? at.thread : null;
|
|
56
|
+
const { thread } = useOpen();
|
|
57
|
+
const [drawer, setDrawer] = useState(false);
|
|
58
|
+
// An address names Chat's conversation, and one just begun writes its id back.
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (mode !== 'chat')
|
|
61
|
+
return;
|
|
62
|
+
if (asked && asked !== thread)
|
|
63
|
+
openThread(asked);
|
|
64
|
+
else if (!asked && thread)
|
|
65
|
+
empty();
|
|
66
|
+
// The address decides; the selection follows it.
|
|
67
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
68
|
+
}, [mode, asked]);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (mode === 'chat' && thread && thread !== asked)
|
|
71
|
+
go(talk(thread), true);
|
|
72
|
+
// The selection writes the address only when it moves.
|
|
73
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
74
|
+
}, [mode, thread]);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
last[mode] = `${window.location.pathname}${window.location.search}`;
|
|
77
|
+
setDrawer(false);
|
|
78
|
+
}, [mode, here]);
|
|
79
|
+
const toChat = () => go(last.chat || talk());
|
|
80
|
+
const toDev = () => go(last.dev || app(''));
|
|
81
|
+
return (_jsx(AiProvider, { client: client ?? undefined, children: _jsx(HostProvider, { host: host, children: _jsxs(XStack, { "data-room": "", "data-app": mode, "data-slot": "frame", ...floor, flex: 1, minW: 0, p: "var(--pane-gap)", gap: "var(--pane-gap)", height: "100dvh", overflow: "hidden", "$max-md": {
|
|
82
|
+
p: 0,
|
|
83
|
+
gap: 0,
|
|
84
|
+
bg: 'var(--black)',
|
|
85
|
+
backgroundImage: 'radial-gradient(ellipse 80% 50% at 50% -20%, rgba(255, 255, 255, 0.04), transparent 70%), linear-gradient(180deg, #000000 0%, #030303 50%, #080808 100%)',
|
|
86
|
+
}, children: [_jsx(Column, { host: host, mode: mode, thread: thread, onChat: toChat, onDev: toDev, go: go }), _jsxs(YStack, { "data-slot": "stage", flex: 1, minW: 0, minH: 0, gap: "var(--pane-gap)", "$max-md": { gap: 0 }, children: [_jsxs(XStack, { "data-slot": "app-bar", height: 44, px: "$1", gap: "$1", items: "center", shrink: 0, $md: { display: 'none' }, children: [_jsx(SidebarIconButton, { label: "Open sidebar", onPress: () => setDrawer(true), width: 44, height: 44, rounded: 999, children: _jsx(Menu, { size: 18 }) }), _jsx(Text, { fontSize: "$4", fontWeight: "600", color: "$ink", numberOfLines: 1, children: wordmark(mode) })] }), _jsx(XStack, { "data-slot": "panes", flex: 1, minW: 0, minH: 0, children: mode === 'chat' ? (_jsx(Paned, { framed: true, children: _jsx(Chat, {}) })) : (_jsx(YStack, { render: "main", "data-slot": "pane", ...(run ? null : { ...pane(), overflow: 'hidden' }), flex: 1, minW: 0, minH: 0, children: _jsx(Builder, { host: host, rail: false }) })) })] }), drawer ? (_jsxs(_Fragment, { children: [_jsx(YStack, { render: "button", "aria-label": "Close sidebar", onPress: () => setDrawer(false), ...scrim, position: "absolute", t: 0, r: 0, b: 0, l: 0, z: "var(--z-overlay)", $md: { display: 'none' } }), _jsx(YStack, { "data-slot": "drawer", position: "absolute", t: "var(--pane-gap)", b: "var(--pane-gap)", l: "var(--pane-gap)", width: "min(320px, calc(100% - 2 * var(--pane-gap) - 48px))", z: "var(--z-modal)", $md: { display: 'none' }, children: _jsx(Column, { host: host, mode: mode, thread: thread, onChat: toChat, onDev: toDev, go: go, drawer: true }) })] })) : null] }) }) }));
|
|
87
|
+
}
|
package/dist/Settings.js
CHANGED
|
@@ -104,7 +104,7 @@ const GROUPS = [
|
|
|
104
104
|
{ id: 'base', label: 'Base', href: site('/base') },
|
|
105
105
|
{ id: 'functions', label: 'Functions', href: site('/functions') },
|
|
106
106
|
{ id: 'realtime', label: 'Realtime', href: site('/realtime') },
|
|
107
|
-
{ id: 'keys', label: 'API keys' },
|
|
107
|
+
{ id: 'keys', label: 'API keys', href: 'https://platform.hanzo.ai/api-keys' },
|
|
108
108
|
],
|
|
109
109
|
},
|
|
110
110
|
];
|
|
@@ -156,8 +156,6 @@ function Pane({ id, note }) {
|
|
|
156
156
|
return _jsx(Billing, {});
|
|
157
157
|
if (id === 'usage')
|
|
158
158
|
return _jsx(Usage, {});
|
|
159
|
-
if (id === 'keys')
|
|
160
|
-
return _jsx(Keys, {});
|
|
161
159
|
if (id === 'model')
|
|
162
160
|
return _jsx(Model, {});
|
|
163
161
|
if (id === 'models')
|
|
@@ -262,10 +260,6 @@ function Usage() {
|
|
|
262
260
|
// account that had spent nothing.
|
|
263
261
|
return (_jsxs(YStack, { gap: "$6", children: [plan, _jsx(UsagePanel, { baseUrl: api(), token: accessToken, upgrade: payPage(), title: "Spend" })] }));
|
|
264
262
|
}
|
|
265
|
-
/** Keys are minted and revoked through the console, which holds the one issuer. */
|
|
266
|
-
function Keys() {
|
|
267
|
-
return (_jsxs(YStack, { gap: "$2", children: [_jsx(Text, { fontSize: "$3", color: "$soft", children: "A key is shown once, at the moment it is minted. That happens where the issuer lives." }), _jsx(XStack, { children: _jsx(Box, { render: _jsx("a", { href: "https://platform.hanzo.ai/api-keys", target: "_blank", rel: "noreferrer" }), ...tap, children: _jsxs(XStack, { items: "center", gap: "$2", py: "$2", children: [_jsx(Text, { fontSize: "$3", color: "$ink", children: "Manage API keys" }), _jsx(ExternalLink, { size: 13, "aria-hidden": true })] }) }) })] }));
|
|
268
|
-
}
|
|
269
263
|
const HISTORICAL_PERSONAS = [
|
|
270
264
|
{ id: 'architect', name: 'Software Architect', role: 'Full-stack & systems design' },
|
|
271
265
|
{ id: 'satoshi', name: 'Satoshi Nakamoto', role: 'Distributed cryptography & consensus' },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/rooms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.45",
|
|
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",
|