@hanzo/build 0.2.3 → 0.2.4
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/sessions.d.ts +2 -0
- package/lib/api/sessions.js +1 -0
- package/lib/api/turn.d.ts +5 -2
- package/lib/api/turn.js +10 -5
- package/lib/data.js +1 -0
- package/lib/project.js +4 -4
- package/lib/run.js +2 -2
- package/package.json +1 -1
package/lib/api/sessions.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export interface Session {
|
|
|
31
31
|
branch: string;
|
|
32
32
|
/** 'sandbox', or the id of the org's machine it runs on. */
|
|
33
33
|
environment: string;
|
|
34
|
+
/** 'build' or 'plan', as the coding service recorded it; '' for other runs. */
|
|
35
|
+
mode: string;
|
|
34
36
|
/** The pull request the run proposed, or ''. */
|
|
35
37
|
pr: string;
|
|
36
38
|
events: number;
|
package/lib/api/sessions.js
CHANGED
package/lib/api/turn.d.ts
CHANGED
|
@@ -16,8 +16,11 @@
|
|
|
16
16
|
import type { Event } from './sessions.ts';
|
|
17
17
|
/** The payload as an object. A live frame may carry it as a JSON string. */
|
|
18
18
|
export declare function decode(payload: unknown): Record<string, unknown> | string | null;
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* One event's sentence, or '' when it says nothing a person needs. `mode` is
|
|
21
|
+
* the run's, from its record: a plan run's final status says the plan.
|
|
22
|
+
*/
|
|
23
|
+
export declare function said(e: Pick<Event, 'kind' | 'payload'>, mode?: string): string;
|
|
21
24
|
export interface Outcome {
|
|
22
25
|
/** The last lifecycle status the run narrated, or ''. */
|
|
23
26
|
status: string;
|
package/lib/api/turn.js
CHANGED
|
@@ -23,7 +23,7 @@ const base = (path) => {
|
|
|
23
23
|
const cut = path.replace(/\/+$/, '');
|
|
24
24
|
return cut.slice(cut.lastIndexOf('/') + 1);
|
|
25
25
|
};
|
|
26
|
-
function status(b) {
|
|
26
|
+
function status(b, mode) {
|
|
27
27
|
const branch = str(b.branch);
|
|
28
28
|
switch (str(b.status)) {
|
|
29
29
|
case 'started':
|
|
@@ -32,7 +32,9 @@ function status(b) {
|
|
|
32
32
|
return 'Sent to a machine';
|
|
33
33
|
case 'done': {
|
|
34
34
|
// A plan's answer IS its final status: the run read and wrote nothing.
|
|
35
|
-
|
|
35
|
+
// Whether the run planned is the RECORD's word — any member of the org
|
|
36
|
+
// can append an event saying `mode: plan`, and its text is not an answer.
|
|
37
|
+
if (mode === 'plan')
|
|
36
38
|
return str(b.plan) || 'Planned — the run answered with no plan';
|
|
37
39
|
if (b.changed === false)
|
|
38
40
|
return 'Done — nothing to change';
|
|
@@ -49,15 +51,18 @@ function status(b) {
|
|
|
49
51
|
}
|
|
50
52
|
return str(b.status);
|
|
51
53
|
}
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
+
/**
|
|
55
|
+
* One event's sentence, or '' when it says nothing a person needs. `mode` is
|
|
56
|
+
* the run's, from its record: a plan run's final status says the plan.
|
|
57
|
+
*/
|
|
58
|
+
export function said(e, mode = '') {
|
|
54
59
|
const body = decode(e.payload);
|
|
55
60
|
if (typeof body === 'string')
|
|
56
61
|
return body;
|
|
57
62
|
if (!body)
|
|
58
63
|
return '';
|
|
59
64
|
if (e.kind === 'status')
|
|
60
|
-
return status(body);
|
|
65
|
+
return status(body, mode);
|
|
61
66
|
for (const key of ['message', 'text', 'content', 'result', 'command']) {
|
|
62
67
|
const v = body[key];
|
|
63
68
|
if (typeof v === 'string' && v)
|
package/lib/data.js
CHANGED
|
@@ -172,6 +172,7 @@ export function useRun(t, id) {
|
|
|
172
172
|
title: pushed.title || base.title,
|
|
173
173
|
branch: pushed.branch || base.branch,
|
|
174
174
|
pr: pushed.pr || base.pr,
|
|
175
|
+
mode: pushed.mode || base.mode,
|
|
175
176
|
};
|
|
176
177
|
}, [read, frame]);
|
|
177
178
|
return { detail, record, events, status: record?.status ?? '', refused };
|
package/lib/project.js
CHANGED
|
@@ -133,13 +133,13 @@ export function Project({ slug }) {
|
|
|
133
133
|
.filter((e) => e.kind === 'log' || e.kind === 'tool-call' || e.kind === 'status')
|
|
134
134
|
.map((e) => ({
|
|
135
135
|
id: `r${e.seq || e.id}`,
|
|
136
|
-
level: e.kind === 'status' && /error/.test(said(e).toLowerCase()) ? 'error' : e.kind === 'tool-call' ? 'info' : 'log',
|
|
137
|
-
text: said(e),
|
|
136
|
+
level: e.kind === 'status' && /error/.test(said(e, run.record?.mode).toLowerCase()) ? 'error' : e.kind === 'tool-call' ? 'info' : 'log',
|
|
137
|
+
text: said(e, run.record?.mode),
|
|
138
138
|
source: e.kind === 'status' ? 'run' : who(e.actor),
|
|
139
139
|
}))
|
|
140
140
|
.filter((l) => l.text),
|
|
141
141
|
...pageLines,
|
|
142
|
-
], [run.events, pageLines]);
|
|
142
|
+
], [run.events, run.record?.mode, pageLines]);
|
|
143
143
|
const onBridge = (e) => {
|
|
144
144
|
if (e.type === 'preview:ready') {
|
|
145
145
|
setBridge(true);
|
|
@@ -227,7 +227,7 @@ export function Project({ slug }) {
|
|
|
227
227
|
}
|
|
228
228
|
const chat = (_jsxs(YStack, { flex: 1, minH: 0, children: [_jsx(YStack, { flex: 1, minH: 0, overflow: "scroll", px: "$3", py: "$4", gap: "$4", children: ordered.length === 0 ? (_jsx(SizableText, { size: "$2", color: "$ink", px: "$2", children: runs.loading
|
|
229
229
|
? 'Reading this project’s runs…'
|
|
230
|
-
: `${project?.name ?? slug} is loaded — it is in the preview, and every run on it is under the clock above. Say what to change and it gets built.` })) : (ordered.map((r) => (_jsxs(YStack, { gap: "$2", children: [_jsx(Turn, { run: r, open: r.id === current, onOpen: () => setChosen(r.id), project: slug }), r.id === current ? (_jsxs(YStack, { gap: "$1", pl: "$2", borderLeftWidth: 1, borderColor: "$borderColor", children: [fold(run.events.map((e) => ({ kind: e.kind, actor: who(e.actor), seq: e.seq, id: e.id, text: said(e) })).filter((b) => b.text)).map((b) => (_jsx(SizableText, { size: "$1", color: "$soft", children: b.text }, b.key))), pr.href ? (_jsxs(Out, { href: pr.href, label: `Open pull request ${pr.label}`, children: [_jsxs(SizableText, { size: "$1", color: "$ink", textDecorationLine: "underline", children: ["Pull request ", pr.label] }), _jsx(ExternalLink, { size: 11 })] })) : null] })) : null] }, r.id)))) }), _jsxs(YStack, { px: "$3", pb: "$3", gap: "$2", children: [!dismissed && !running ? _jsx(Suggestions, { items: SUGGESTIONS, onPick: (s) => void send(s), onDismiss: () => setDismissed(true) }) : null, note || unhonoured(mode) ? (_jsx(SizableText, { size: "$1", color: "$soft", role: "status", children: note || unhonoured(mode) })) : null, picked.length ? _jsx(Attachments, { items: picked, onRemove: () => setPicked([]) }) : null, attached.length ? (_jsx(XStack, { gap: 6, flexWrap: "wrap", children: _jsx(Files, { files: attached, onFiles: setAttached }) })) : null, _jsxs(Composer, { value: draft, onChange: setDraft, onSend: () => void (running ? steer() : send()), onStop: current ? () => void stop(t, current).then(() => setNote('Stop requested — the run keeps its work on its branch')) : undefined, busy: busy || (running && !draft.trim()), rows: 3, placeholder: running ? 'Steer this run' : 'Ask Hanzo for edits', label: "Ask Hanzo for edits", children: [_jsx(Attach, { files: attached, onFiles: setAttached, onNote: setNote }), _jsx(XStack, { flex: 1 }), _jsx(ModeSelect, { modes: MODES, value: mode, onChange: (m) => setMode(m), self: "center" }), _jsx(Dictate, { onText: (said) => setDraft((d) => (d ? `${d} ${said}` : said)), onNote: setNote })] })] })] }));
|
|
230
|
+
: `${project?.name ?? slug} is loaded — it is in the preview, and every run on it is under the clock above. Say what to change and it gets built.` })) : (ordered.map((r) => (_jsxs(YStack, { gap: "$2", children: [_jsx(Turn, { run: r, open: r.id === current, onOpen: () => setChosen(r.id), project: slug }), r.id === current ? (_jsxs(YStack, { gap: "$1", pl: "$2", borderLeftWidth: 1, borderColor: "$borderColor", children: [fold(run.events.map((e) => ({ kind: e.kind, actor: who(e.actor), seq: e.seq, id: e.id, text: said(e, run.record?.mode) })).filter((b) => b.text)).map((b) => (_jsx(SizableText, { size: "$1", color: "$soft", children: b.text }, b.key))), pr.href ? (_jsxs(Out, { href: pr.href, label: `Open pull request ${pr.label}`, children: [_jsxs(SizableText, { size: "$1", color: "$ink", textDecorationLine: "underline", children: ["Pull request ", pr.label] }), _jsx(ExternalLink, { size: 11 })] })) : null] })) : null] }, r.id)))) }), _jsxs(YStack, { px: "$3", pb: "$3", gap: "$2", children: [!dismissed && !running ? _jsx(Suggestions, { items: SUGGESTIONS, onPick: (s) => void send(s), onDismiss: () => setDismissed(true) }) : null, note || unhonoured(mode) ? (_jsx(SizableText, { size: "$1", color: "$soft", role: "status", children: note || unhonoured(mode) })) : null, picked.length ? _jsx(Attachments, { items: picked, onRemove: () => setPicked([]) }) : null, attached.length ? (_jsx(XStack, { gap: 6, flexWrap: "wrap", children: _jsx(Files, { files: attached, onFiles: setAttached }) })) : null, _jsxs(Composer, { value: draft, onChange: setDraft, onSend: () => void (running ? steer() : send()), onStop: current ? () => void stop(t, current).then(() => setNote('Stop requested — the run keeps its work on its branch')) : undefined, busy: busy || (running && !draft.trim()), rows: 3, placeholder: running ? 'Steer this run' : 'Ask Hanzo for edits', label: "Ask Hanzo for edits", children: [_jsx(Attach, { files: attached, onFiles: setAttached, onNote: setNote }), _jsx(XStack, { flex: 1 }), _jsx(ModeSelect, { modes: MODES, value: mode, onChange: (m) => setMode(m), self: "center" }), _jsx(Dictate, { onText: (said) => setDraft((d) => (d ? `${d} ${said}` : said)), onNote: setNote })] })] })] }));
|
|
231
231
|
const body = view === 'preview' ? (_jsx(PreviewFrame, { ref: frame, src: src, title: `${project?.name ?? slug} preview`, device: device, onBridge: onBridge, empty: _jsxs(YStack, { items: "center", gap: "$2", p: "$6", children: [_jsx(SizableText, { size: "$3", color: "$ink", children: "Nothing deployed yet" }), _jsx(SizableText, { size: "$2", color: "$soft", text: "center", children: "Publish this project and its page appears here." })] }), toolbar: bridge ? (_jsx(XStack, { render: "button", "aria-pressed": editing, "aria-label": editing ? 'Stop picking elements' : 'Pick an element to edit', onPress: () => {
|
|
232
232
|
const next = !editing;
|
|
233
233
|
setEditing(next);
|
package/lib/run.js
CHANGED
|
@@ -29,8 +29,8 @@ export function Run({ id }) {
|
|
|
29
29
|
const [note, setNote] = useState('');
|
|
30
30
|
const [busy, setBusy] = useState(false);
|
|
31
31
|
const blocks = useMemo(() => fold(events
|
|
32
|
-
.map((e) => ({ kind: e.kind, actor: who(e.actor), seq: e.seq, id: e.id, text: said(e) }))
|
|
33
|
-
.filter((b) => b.text)), [events]);
|
|
32
|
+
.map((e) => ({ kind: e.kind, actor: who(e.actor), seq: e.seq, id: e.id, text: said(e, record?.mode) }))
|
|
33
|
+
.filter((b) => b.text)), [events, record?.mode]);
|
|
34
34
|
const end = outcome(events);
|
|
35
35
|
const state = status || end.status;
|
|
36
36
|
const pr = pull(record?.pr ?? '', record?.repo ?? '');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/build",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
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 page (hanzo.build) and as a component (hanzo.ai/dev).",
|