@hanzo/build 0.2.76 → 0.2.78
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/lib/api/studio.d.ts +3 -2
- package/lib/carry.js +1 -2
- package/lib/design.d.ts +9 -3
- package/lib/design.js +97 -45
- package/lib/prompt.d.ts +2 -1
- package/lib/prompt.js +8 -6
- package/package.json +1 -1
package/lib/api/studio.d.ts
CHANGED
|
@@ -35,8 +35,9 @@ export interface Start {
|
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* A design system: one of Studio's brands, the one store for them. Its tokens
|
|
38
|
-
* are
|
|
39
|
-
*
|
|
38
|
+
* are CSS custom properties (--background, --primary, --font-sans, --radius-md,
|
|
39
|
+
* …, the form Studio's renderer reads), with `--component-*` and `--voice-*` as
|
|
40
|
+
* quoted lines a model follows (design.ts `tokensOf`).
|
|
40
41
|
*
|
|
41
42
|
* GET /v1/studio/brands {data: [brand]} the ones you may read
|
|
42
43
|
* GET /v1/studio/brands/{id} one
|
package/lib/carry.js
CHANGED
|
@@ -110,8 +110,7 @@ export function useCarry(t, key, customize, lent, modes = DEV_MODES) {
|
|
|
110
110
|
const named = kits.value.find((b) => b.id === design);
|
|
111
111
|
const designs = {
|
|
112
112
|
rows: kits.value.map((b) => {
|
|
113
|
-
|
|
114
|
-
return { id: b.id, label: b.name, note: [c.primary?.$value, c.accent?.$value].filter(Boolean).join(' '), icon: _jsx(Palette, { size: 16 }), on: b.id === design };
|
|
113
|
+
return { id: b.id, label: b.name, note: [b.tokens['--primary'], b.tokens['--accent']].filter((x) => typeof x === 'string').join(' '), icon: _jsx(Palette, { size: 16 }), on: b.id === design };
|
|
115
114
|
}),
|
|
116
115
|
pick: (id) => gear.set({ design: design === id ? '' : id }),
|
|
117
116
|
loading: kits.loading,
|
package/lib/design.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A design system as the composer handles it: drafted by a model, kept as a
|
|
3
|
-
* Studio brand (
|
|
3
|
+
* Studio brand (CSS custom properties, the form Studio's renderer reads), said to the
|
|
4
4
|
* model on every message of a conversation it is attached to, and drawn as a
|
|
5
5
|
* page to look at. Pure, so it is tested without a browser.
|
|
6
6
|
*/
|
|
@@ -126,8 +126,14 @@ export declare const SCHEMA: {
|
|
|
126
126
|
};
|
|
127
127
|
/** A model's answer as a Draft, or why it is not one. */
|
|
128
128
|
export declare function drafted(raw: unknown): Draft | string;
|
|
129
|
-
/**
|
|
130
|
-
|
|
129
|
+
/**
|
|
130
|
+
* A Draft as design tokens: CSS custom properties, the names @hanzo/design uses
|
|
131
|
+
* (--background, --foreground, --primary, --font-sans, …). That is the one form
|
|
132
|
+
* Studio's renderer takes (hanzo/render `tokens`: every key `--name`, every value
|
|
133
|
+
* one declaration), so a deck, a document and a page draw from the same map.
|
|
134
|
+
* The components and the voice ride along as quoted strings under their own names.
|
|
135
|
+
*/
|
|
136
|
+
export declare function tokensOf(d: Draft): Record<string, string>;
|
|
131
137
|
/** What a model is told on every message of a conversation the system is attached to. */
|
|
132
138
|
export declare function said(b: Brand): string;
|
|
133
139
|
/** The system drawn as a page: its palette, type, a button, a card, an input, its voice. */
|
package/lib/design.js
CHANGED
|
@@ -54,40 +54,92 @@ export function drafted(raw) {
|
|
|
54
54
|
voice: { tone: str(v.tone), do: lines(v.do), dont: lines(v.dont) },
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* A Draft as design tokens: CSS custom properties, the names @hanzo/design uses
|
|
59
|
+
* (--background, --foreground, --primary, --font-sans, …). That is the one form
|
|
60
|
+
* Studio's renderer takes (hanzo/render `tokens`: every key `--name`, every value
|
|
61
|
+
* one declaration), so a deck, a document and a page draw from the same map.
|
|
62
|
+
* The components and the voice ride along as quoted strings under their own names.
|
|
63
|
+
*/
|
|
58
64
|
export function tokensOf(d) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
components: Object.fromEntries(Object.entries(d.components).map(([k, v]) => [k, { $value: v, $type: 'string' }])),
|
|
67
|
-
voice: { tone: { $value: d.voice.tone, $type: 'string' }, do: { $value: d.voice.do, $type: 'string' }, dont: { $value: d.voice.dont, $type: 'string' } },
|
|
65
|
+
// Quoted, with nothing that would make JSON escape it or end the declaration.
|
|
66
|
+
const q = (v) => JSON.stringify(v.replace(/["\\;{}<>\u0000-\u001f]|\/\*/g, ' ').slice(0, 280));
|
|
67
|
+
const c = d.colors;
|
|
68
|
+
const out = {
|
|
69
|
+
'--background': c.background,
|
|
70
|
+
'--foreground': c.text,
|
|
71
|
+
'--primary': c.primary,
|
|
68
72
|
};
|
|
73
|
+
const more = { '--secondary': c.secondary, '--accent': c.accent, '--card': c.surface, '--muted-foreground': c.muted, '--border': c.border };
|
|
74
|
+
for (const [k, v] of Object.entries(more))
|
|
75
|
+
if (v)
|
|
76
|
+
out[k] = v;
|
|
77
|
+
out['--font-display'] = d.fonts.heading;
|
|
78
|
+
out['--font-sans'] = d.fonts.body;
|
|
79
|
+
out['--font-mono'] = d.fonts.mono;
|
|
80
|
+
for (const [k, v] of Object.entries(d.radius))
|
|
81
|
+
out[`--radius-${k}`] = `${v}px`;
|
|
82
|
+
d.scale.forEach((n, i) => (out[`--text-${i}`] = `${n}px`));
|
|
83
|
+
d.spacing.forEach((n, i) => (out[`--space-${i}`] = `${n}px`));
|
|
84
|
+
for (const [k, v] of Object.entries(d.components))
|
|
85
|
+
out[`--component-${k.replace(/[^a-z0-9-]/gi, '-').toLowerCase()}`] = q(v);
|
|
86
|
+
if (d.voice.tone)
|
|
87
|
+
out['--voice-tone'] = q(d.voice.tone);
|
|
88
|
+
if (d.voice.do.length)
|
|
89
|
+
out['--voice-do'] = q(d.voice.do.join('; ').replace(/;/g, ','));
|
|
90
|
+
if (d.voice.dont.length)
|
|
91
|
+
out['--voice-dont'] = q(d.voice.dont.join('; ').replace(/;/g, ','));
|
|
92
|
+
return out;
|
|
69
93
|
}
|
|
70
|
-
/**
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return
|
|
75
|
-
}
|
|
94
|
+
/** A token's value as written, a quoted string unquoted. */
|
|
95
|
+
const value = (v) => {
|
|
96
|
+
const s = typeof v === 'string' ? v : '';
|
|
97
|
+
try {
|
|
98
|
+
return s.startsWith('"') ? String(JSON.parse(s)) : s;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return s;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
/** The tokens whose names start `prefix`, as `name value` pairs, the prefix dropped. */
|
|
105
|
+
function pairs(tokens, prefix) {
|
|
106
|
+
return Object.entries(tokens)
|
|
107
|
+
.filter(([k]) => k.startsWith(prefix))
|
|
108
|
+
.map(([k, v]) => [k.slice(prefix.length), value(v)]);
|
|
76
109
|
}
|
|
110
|
+
/** The colours by the names a person reads them. */
|
|
111
|
+
const COLOURS = [
|
|
112
|
+
['primary', '--primary'],
|
|
113
|
+
['secondary', '--secondary'],
|
|
114
|
+
['accent', '--accent'],
|
|
115
|
+
['background', '--background'],
|
|
116
|
+
['surface', '--card'],
|
|
117
|
+
['text', '--foreground'],
|
|
118
|
+
['muted', '--muted-foreground'],
|
|
119
|
+
['border', '--border'],
|
|
120
|
+
];
|
|
121
|
+
const colours = (t) => COLOURS.filter(([, k]) => t[k]).map(([n, k]) => [n, value(t[k])]);
|
|
77
122
|
/** What a model is told on every message of a conversation the system is attached to. */
|
|
78
123
|
export function said(b) {
|
|
79
124
|
const t = b.tokens;
|
|
80
|
-
const row = (
|
|
125
|
+
const row = (list) => list.map(([k, v]) => `${k} ${v}`).join(', ');
|
|
126
|
+
const fonts = [
|
|
127
|
+
['heading', value(t['--font-display'])],
|
|
128
|
+
['body', value(t['--font-sans'])],
|
|
129
|
+
['mono', value(t['--font-mono'])],
|
|
130
|
+
].filter(([, v]) => v);
|
|
131
|
+
const comps = pairs(t, '--component-');
|
|
132
|
+
const voice = [value(t['--voice-tone']), value(t['--voice-do']) && `do: ${value(t['--voice-do'])}`, value(t['--voice-dont']) && `don't: ${value(t['--voice-dont'])}`].filter(Boolean);
|
|
81
133
|
const parts = [
|
|
82
134
|
`Design system "${b.name}" is attached to this conversation. Everything you make — pages, apps, components, slides, images and copy — follows it exactly; never invent other colours, fonts or radii.`,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
135
|
+
colours(t).length && `Colours: ${row(colours(t))}.`,
|
|
136
|
+
fonts.length && `Fonts: ${row(fonts)}.`,
|
|
137
|
+
pairs(t, '--text-').length && `Type scale: ${row(pairs(t, '--text-'))}.`,
|
|
138
|
+
pairs(t, '--space-').length && `Spacing: ${row(pairs(t, '--space-'))}.`,
|
|
139
|
+
pairs(t, '--radius-').length && `Radius: ${row(pairs(t, '--radius-'))}.`,
|
|
140
|
+
comps.length && `Components: ${comps.map(([k, v]) => `${k} — ${v}`).join(' ')}`,
|
|
141
|
+
voice.length && `Voice: ${voice.join(' | ')}`,
|
|
142
|
+
`In HTML, declare these exact custom properties on :root and use them: ${Object.keys(t).filter((k) => !k.startsWith('--component-') && !k.startsWith('--voice-')).join(', ')}. Load the fonts from Google Fonts when they are web fonts.`,
|
|
91
143
|
];
|
|
92
144
|
return parts.filter(Boolean).join('\n');
|
|
93
145
|
}
|
|
@@ -95,29 +147,29 @@ const esc = (s) => s.replace(/[&<>"]/g, (c) => ({ '&': '&', '<': '<', '>'
|
|
|
95
147
|
/** The system drawn as a page: its palette, type, a button, a card, an input, its voice. */
|
|
96
148
|
export function preview(b) {
|
|
97
149
|
const t = b.tokens;
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
const fonts = [f.heading, f.body].filter((x) => x && !/^ui-|system|sans-serif|serif$/i.test(x));
|
|
150
|
+
const v = (k, d) => value(t[k]) || d;
|
|
151
|
+
const sizes = pairs(t, '--text-').map(([, x]) => x);
|
|
152
|
+
const comps = pairs(t, '--component-');
|
|
153
|
+
const heading = v('--font-display', 'Inter');
|
|
154
|
+
const body = v('--font-sans', 'Inter');
|
|
155
|
+
const fonts = [heading, body].filter((x) => x && !/^ui-|system|sans-serif|serif$/i.test(x));
|
|
105
156
|
const link = fonts.length ? `<link rel="stylesheet" href="https://fonts.googleapis.com/css2?${fonts.map((x) => `family=${encodeURIComponent(x)}:wght@400;600;700`).join('&')}&display=swap">` : '';
|
|
106
|
-
const swatches =
|
|
107
|
-
const scale = sizes.map((
|
|
157
|
+
const swatches = colours(t).map(([k, c]) => `<div class="sw"><span style="background:${esc(c)}"></span><b>${esc(k)}</b><code>${esc(c)}</code></div>`).join('');
|
|
158
|
+
const scale = sizes.map((x) => `<div style="font-size:${esc(x)}">${esc(b.name)} — ${esc(x)}</div>`).join('');
|
|
159
|
+
const root = Object.entries(t).filter(([k]) => !k.startsWith('--component-') && !k.startsWith('--voice-')).map(([k, x]) => `${k}:${value(x)}`).join(';');
|
|
108
160
|
return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${esc(b.name)}</title>${link}
|
|
109
|
-
<style>:root{
|
|
110
|
-
body{margin:0;background:var(--
|
|
111
|
-
h1,h2{font-family:'${esc(
|
|
112
|
-
.row{display:flex;flex-wrap:wrap;gap:16px}.sw{display:flex;flex-direction:column;gap:4px;width:120px}.sw span{height:64px;border-radius:var(--
|
|
113
|
-
.btn{background:var(--primary);color:var(--
|
|
114
|
-
.card{background:var(--
|
|
115
|
-
li{color:var(--muted)}</style></head><body>
|
|
116
|
-
<h1 style="font-size:40px">${esc(b.name)}</h1><p style="color:var(--muted)">${esc(voice
|
|
161
|
+
<style>:root{${root}}
|
|
162
|
+
body{margin:0;background:var(--background);color:var(--foreground);font-family:'${esc(body)}',system-ui,sans-serif;padding:40px;line-height:1.5}
|
|
163
|
+
h1,h2{font-family:'${esc(heading)}',system-ui,sans-serif;margin:0 0 12px}h2{margin-top:40px;font-size:14px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted-foreground,var(--foreground))}
|
|
164
|
+
.row{display:flex;flex-wrap:wrap;gap:16px}.sw{display:flex;flex-direction:column;gap:4px;width:120px}.sw span{height:64px;border-radius:var(--radius-md,8px);border:1px solid var(--border,var(--foreground))}.sw code{color:var(--muted-foreground);font-size:12px}
|
|
165
|
+
.btn{background:var(--primary);color:var(--background);border:0;border-radius:var(--radius-md,8px);padding:12px 20px;font:inherit;font-weight:600}.btn.ghost{background:transparent;color:var(--foreground);border:1px solid var(--border,var(--foreground))}
|
|
166
|
+
.card{background:var(--card,var(--background));border:1px solid var(--border,var(--foreground));border-radius:var(--radius-lg,16px);padding:20px;max-width:320px}input{background:var(--card,var(--background));color:var(--foreground);border:1px solid var(--border,var(--foreground));border-radius:var(--radius-sm,4px);padding:10px 12px;font:inherit;width:260px}
|
|
167
|
+
li{color:var(--muted-foreground)}</style></head><body>
|
|
168
|
+
<h1 style="font-size:40px">${esc(b.name)}</h1><p style="color:var(--muted-foreground)">${esc(value(t['--voice-tone']))}</p>
|
|
117
169
|
<h2>Colour</h2><div class="row">${swatches}</div>
|
|
118
170
|
<h2>Type</h2>${scale}
|
|
119
|
-
<h2>Components</h2><div class="row" style="align-items:flex-start"><button class="btn">Primary action</button><button class="btn ghost">Secondary</button><input placeholder="An input"><div class="card"><b>A card</b><p style="color:var(--muted);margin:8px 0 0">${esc(comps.find(([k]) => k === 'card')?.[1] ?? '')}</p></div></div>
|
|
120
|
-
<ul>${comps.map(([k,
|
|
121
|
-
<h2>Voice</h2><p><b>Do</b>: ${esc(voice
|
|
171
|
+
<h2>Components</h2><div class="row" style="align-items:flex-start"><button class="btn">Primary action</button><button class="btn ghost">Secondary</button><input placeholder="An input"><div class="card"><b>A card</b><p style="color:var(--muted-foreground);margin:8px 0 0">${esc(comps.find(([k]) => k === 'card')?.[1] ?? '')}</p></div></div>
|
|
172
|
+
<ul>${comps.map(([k, x]) => `<li><b style="color:var(--foreground)">${esc(k)}</b> — ${esc(x)}</li>`).join('')}</ul>
|
|
173
|
+
<h2>Voice</h2><p><b>Do</b>: ${esc(value(t['--voice-do']))}</p><p><b>Don't</b>: ${esc(value(t['--voice-dont']))}</p>
|
|
122
174
|
</body></html>`;
|
|
123
175
|
}
|
package/lib/prompt.d.ts
CHANGED
|
@@ -94,11 +94,12 @@ export interface PromptOptions {
|
|
|
94
94
|
narrow?: boolean;
|
|
95
95
|
}
|
|
96
96
|
/** The row under the frame: where (Dev), then the model, the effort and the mode. */
|
|
97
|
-
export declare function Tune({ mind, mode, where, onUpgrade }: {
|
|
97
|
+
export declare function Tune({ mind, mode, where, onUpgrade, limits }: {
|
|
98
98
|
mind?: Mind | null;
|
|
99
99
|
mode?: PromptOptions['mode'];
|
|
100
100
|
where?: ReactNode;
|
|
101
101
|
onUpgrade?: (model: string) => void;
|
|
102
|
+
limits?: PauseSource | null;
|
|
102
103
|
}): import("react").JSX.Element;
|
|
103
104
|
/** The `/` or `@` the caret ends on, and the words typed after it. */
|
|
104
105
|
export declare function trigger(value: string): {
|
package/lib/prompt.js
CHANGED
|
@@ -23,7 +23,7 @@ import { ArrowUp, AudioLines, Check, Square, X } from '@hanzogui/lucide-icons-2'
|
|
|
23
23
|
import { Control } from '@hanzo/composer';
|
|
24
24
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSearch, DropdownMenuTrigger, Popover, PopoverContent, PopoverTrigger } from '@hanzo/ui';
|
|
25
25
|
import { Composer } from '@hanzo/ui/chat';
|
|
26
|
-
import { groupModels, matchesModel } from '@hanzo/ui/models';
|
|
26
|
+
import { groupModels, isPaused, matchesModel } from '@hanzo/ui/models';
|
|
27
27
|
import { speech, Voice } from '@hanzo/voice';
|
|
28
28
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
29
29
|
import { ENSO } from './api/models.js';
|
|
@@ -81,7 +81,7 @@ function Opens({ label, word, dim, children }) {
|
|
|
81
81
|
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, allowFlip: true, placement: "top-end", children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(XStack, { children: _jsx(Word, { label: label, dim: dim, open: open, children: word }) }) }), _jsx(PopoverContent, { solid: true, p: 6, width: 288, maxW: "calc(100vw - 24px)", children: children(() => setOpen(false)) })] }));
|
|
82
82
|
}
|
|
83
83
|
/** The model's name, and the catalog behind it: Free's lane to pick from, the rest an upgrade. */
|
|
84
|
-
function Model({ mind, onUpgrade }) {
|
|
84
|
+
function Model({ mind, onUpgrade, limits }) {
|
|
85
85
|
const [open, setOpen] = useState(false);
|
|
86
86
|
const [q, setQ] = useState('');
|
|
87
87
|
// The catalog is hundreds long, and drawing all of it is what made the menu slow
|
|
@@ -103,14 +103,16 @@ function Model({ mind, onUpgrade }) {
|
|
|
103
103
|
const routed = mind.model === ENSO;
|
|
104
104
|
return (_jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, placement: "top-end", children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(XStack, { "data-slot": "mind", children: _jsx(Word, { label: `Model: ${nameOf(mind.model, mind.models)}`, open: open, children: nameOf(mind.model, mind.models) }) }) }), _jsxs(DropdownMenuContent, { align: "end", minW: 280, "data-slot": "model-menu", children: [_jsx(DropdownMenuSearch, { value: q, onValueChange: setQ, placeholder: "Search models" }), _jsxs(YStack, { maxH: "min(420px, 60vh)", overflowY: "auto", overflowX: "hidden", "data-slot": "model-rows", children: [!mind.free && !q.trim() ? (_jsx(DropdownMenuItem, { onSelect: () => mind.pick(ENSO), children: _jsxs(XStack, { flex: 1, items: "center", gap: 8, children: [_jsxs(YStack, { flex: 1, children: [_jsx(SizableText, { fontSize: 14, color: "$ink", children: "Enso" }), _jsx(SizableText, { fontSize: 12, color: "$hint", children: "Picks the model for each message and step" })] }), routed ? _jsx(Check, { size: 14, color: "var(--primary)", "aria-hidden": true }) : null] }) })) : null, groups.map((g) => (_jsxs(YStack, { role: "group", "aria-label": g.label, children: [_jsx(SizableText, { fontSize: 12, color: "$hint", px: 8, pt: 8, pb: 2, children: g.label }), g.models.map((m) => {
|
|
105
105
|
const ok = grants(mind.free, m.id, mind.models);
|
|
106
|
-
|
|
106
|
+
// Paused by the plan's usage: still listed and still picked; the gateway answers from Enso.
|
|
107
|
+
const paused = isPaused(m, limits);
|
|
108
|
+
return (_jsx(DropdownMenuItem, { "data-slot": "model-row", "data-model": m.id, "data-paused": paused ? 'true' : undefined, onSelect: () => (ok ? mind.pick(m.id) : onUpgrade?.(m.id)), children: _jsxs(XStack, { flex: 1, items: "center", gap: 8, children: [_jsx(SizableText, { fontSize: 14, color: ok ? '$ink' : '$hint', numberOfLines: 1, flex: 1, children: nameOf(m.id, mind.models) }), ok ? null : (_jsx(SizableText, { fontSize: 12, color: "$hint", px: 6, py: 1, rounded: 6, borderWidth: 1, borderColor: "$borderColor", children: "Upgrade" })), ok && paused ? (_jsx(SizableText, { fontSize: 12, color: "$hint", children: "Paused" })) : null, m.id === mind.model ? _jsx(Check, { size: 14, color: "var(--primary)", "aria-hidden": true }) : null] }) }, m.id));
|
|
107
109
|
})] }, g.key))), more > 0 ? (_jsx(SizableText, { fontSize: 12, color: "$hint", px: 8, py: 8, children: `Type to search ${more} more models` })) : null] })] })] }));
|
|
108
110
|
}
|
|
109
111
|
/** The row under the frame: where (Dev), then the model, the effort and the mode. */
|
|
110
|
-
export function Tune({ mind, mode, where, onUpgrade }) {
|
|
112
|
+
export function Tune({ mind, mode, where, onUpgrade, limits }) {
|
|
111
113
|
const thinks = mind ? reasons(mind.model, mind.models) : false;
|
|
112
114
|
const pace = mind ? EFFORTS.find((e) => e.id === mind.effort) : null;
|
|
113
|
-
return (_jsxs(XStack, { "data-slot": "tune", width: "100%", items: "center", gap: 2, flexWrap: "wrap", rowGap: 4, children: [where ? (_jsx(XStack, { items: "center", gap: 2, flexWrap: "wrap", minW: 0, "$max-sm": { width: '100%' }, children: where })) : null, _jsx(XStack, { flex: 1, "$max-sm": { display: 'none' } }), _jsxs(XStack, { items: "center", gap: 2, ml: "auto", shrink: 0, children: [mind ? _jsx(Model, { mind: mind, onUpgrade: onUpgrade }) : null, mind && thinks && pace ? (_jsx(Opens, { label: `Effort: ${pace.label}`, word: pace.label, dim: true, children: (close) => (_jsx(Choices, { title: "Effort", items: EFFORTS, value: mind.effort, onPick: (e) => {
|
|
115
|
+
return (_jsxs(XStack, { "data-slot": "tune", width: "100%", items: "center", gap: 2, flexWrap: "wrap", rowGap: 4, children: [where ? (_jsx(XStack, { items: "center", gap: 2, flexWrap: "wrap", minW: 0, "$max-sm": { width: '100%' }, children: where })) : null, _jsx(XStack, { flex: 1, "$max-sm": { display: 'none' } }), _jsxs(XStack, { items: "center", gap: 2, ml: "auto", shrink: 0, children: [mind ? _jsx(Model, { mind: mind, onUpgrade: onUpgrade, limits: limits }) : null, mind && thinks && pace ? (_jsx(Opens, { label: `Effort: ${pace.label}`, word: pace.label, dim: true, children: (close) => (_jsx(Choices, { title: "Effort", items: EFFORTS, value: mind.effort, onPick: (e) => {
|
|
114
116
|
mind.pace(e);
|
|
115
117
|
close();
|
|
116
118
|
} })) })) : null, mode ? (_jsxs(Popover, { allowFlip: true, placement: "top-end", children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(XStack, { render: "button", "data-slot": "mode", "aria-label": `Mode: ${MODES.find((m) => m.id === mode.value)?.label}`, items: "center", height: 24, px: 8, ml: 4, rounded: 6, bg: "$hover", cursor: "pointer", hoverStyle: { bg: '$raised' }, focusVisibleStyle: { outlineColor: '$outlineColor', outlineWidth: 2, outlineStyle: 'solid' }, "$max-sm": { height: 44, px: 12 }, children: _jsx(SizableText, { fontSize: 14, color: "$ink", children: MODES.find((m) => m.id === mode.value)?.label }) }) }), _jsx(PopoverContent, { solid: true, p: 6, width: 288, maxW: "calc(100vw - 24px)", children: _jsx(Choices, { title: "Mode", items: mode.items ? MODES.filter((m) => mode.items.includes(m.id)) : MODES, value: mode.value, onPick: mode.set }) })] })) : null] })] }));
|
|
@@ -144,7 +146,7 @@ export function prompt(o, state) {
|
|
|
144
146
|
};
|
|
145
147
|
const mention = listed && shelf && typed ? (_jsx(Mention, { shelf: shelf, rows: listed, index: index, onPick: choose, tag: typed.char === '/' ? 'Skill' : 'Plugin', name: typed.char === '/' ? 'Skills' : 'Plugins' })) : null;
|
|
146
148
|
const head = o.head || o.note || mention || (narrow && o.below) ? (_jsxs(YStack, { ...measure, gap: "$1.5", "data-slot": "prompt-head", children: [narrow ? o.below : null, o.head, mention, o.note ? (_jsx(SizableText, { "data-slot": "prompt-note", fontSize: 12, color: "$soft", text: "center", self: "center", children: o.note })) : null] })) : undefined;
|
|
147
|
-
const foot = o.mind || o.mode || o.where || (!narrow && o.below) ? (_jsxs(YStack, { ...measure, gap: 10, "data-slot": "prompt-foot", children: [_jsx(Tune, { mind: o.mind, mode: o.mode, where: o.where, onUpgrade: o.onUpgrade }), narrow ? null : o.below] })) : undefined;
|
|
149
|
+
const foot = o.mind || o.mode || o.where || (!narrow && o.below) ? (_jsxs(YStack, { ...measure, gap: 10, "data-slot": "prompt-foot", children: [_jsx(Tune, { mind: o.mind, mode: o.mode, where: o.where, onUpgrade: o.onUpgrade, limits: o.limits }), narrow ? null : o.below] })) : undefined;
|
|
148
150
|
const round = (_jsx(Control, { type: "button", size: narrow ? TAP : ROUND, fill: true, rounded: 999, "data-slot": "composer-send", "aria-label": busy ? 'Stop' : 'Send', "aria-disabled": !live || undefined, opacity: live ? 1 : 0.4, onClick: () => {
|
|
149
151
|
if (!live)
|
|
150
152
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/build",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.78",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"description": "Hanzo Build — say what you want, watch it built, deployed and running. The builder as a component, mounted by the Hanzo app at hanzo.ai.",
|