wizards 0.5.13 → 0.6.0
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/apps/runtime/dist/authoring/guide.js +63 -7
- package/apps/runtime/dist/credits/estimate.js +1 -1
- package/apps/runtime/dist/engine/requirements.js +1 -1
- package/apps/runtime/dist/engine/runner.js +53 -4
- package/apps/runtime/dist/engine/steps.js +155 -123
- package/apps/runtime/dist/render/downloads.js +16 -3
- package/apps/runtime/dist/render/shaped.js +137 -0
- package/apps/runtime/dist/routes/runs.js +58 -2
- package/apps/runtime/dist/services/brand.js +2 -1
- package/apps/runtime/dist/widgets/runtime.js +25 -2
- package/apps/runtime/dist/widgets/step.js +2 -0
- package/apps/web/dist/assets/AboutDialog-xOyf_juP.js +1 -0
- package/apps/web/dist/assets/{ChangelogDialog-BCS3WIRA.js → ChangelogDialog-vNG0Smoo.js} +1 -1
- package/apps/web/dist/assets/ChatView-BrDkurRe.js +10 -0
- package/apps/web/dist/assets/EditorPage-97U-JYKn.js +3 -0
- package/apps/web/dist/assets/{FlowPreview-D2haAZwo.js → FlowPreview-DA0sHtr7.js} +1 -1
- package/apps/web/dist/assets/{Harness-CGI6ZMTA.js → Harness-Y9E7o83r.js} +2 -2
- package/apps/web/dist/assets/{NewWizardChannels-C4b_phHw.js → NewWizardChannels-D6v1iDOo.js} +1 -1
- package/apps/web/dist/assets/NewWizardPage-BzaAPMUK.js +7 -0
- package/apps/web/dist/assets/{OnboardingPage-DgySdBgo.js → OnboardingPage-9xZAkhuO.js} +1 -1
- package/apps/web/dist/assets/ProjectPage-dQ7wwxD2.js +1 -0
- package/apps/web/dist/assets/PublicRunner-CKa8M0Qd.js +1 -0
- package/apps/web/dist/assets/{ReadOnly-B-4l3bVt.js → ReadOnly-Bqk14yPD.js} +1 -1
- package/apps/web/dist/assets/RunDrawer-DsfZUojZ.js +4 -0
- package/apps/web/dist/assets/{RunnerView-BZ83HUnO.js → RunnerView-D0JQ1fgM.js} +1 -1
- package/apps/web/dist/assets/SettingsPage-Dzu6Fl6b.js +1 -0
- package/apps/web/dist/assets/SetupPage-D2Kl-8NR.js +1 -0
- package/apps/web/dist/assets/SharePage-QSZxUlPt.js +1 -0
- package/apps/web/dist/assets/changelog-XlAAw5Gv.js +1 -0
- package/apps/web/dist/assets/{esm-BqbWrbsa.js → esm-DqRvG-PU.js} +1 -1
- package/apps/web/dist/assets/index-BhVJwBz7.css +1 -0
- package/apps/web/dist/assets/index-mwmrgVFT.js +14 -0
- package/apps/web/dist/assets/{lock-BkN0Fai6.js → lock-D_KjsGfU.js} +1 -1
- package/apps/web/dist/assets/{phone-Dip_wSUZ.js → phone-YRxkPQk6.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-B7eXkvba.js → settings-menu-CQgehwEX.js} +1 -1
- package/apps/web/dist/assets/ui-DDUCc_4v.js +137 -0
- package/apps/web/dist/assets/{upload-DPQ4pwnl.js → upload-DDo14e2p.js} +1 -1
- package/apps/web/dist/index.html +3 -3
- package/apps/web/dist/mcp/flow.html +58 -55
- package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +5 -2
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +187 -3
- package/node_modules/@engenty-wizards/shared/dist/definition.js +89 -18
- package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +11 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.js +54 -0
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +22 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +3 -0
- package/node_modules/@engenty-wizards/shared/dist/runner-texts.d.ts +41 -1
- package/node_modules/@engenty-wizards/shared/dist/runner-texts.js +40 -0
- package/node_modules/@engenty-wizards/shared/dist/runners.js +1 -1
- package/node_modules/@engenty-wizards/shared/dist/shape.d.ts +102 -0
- package/node_modules/@engenty-wizards/shared/dist/shape.js +318 -0
- package/node_modules/@engenty-wizards/shared/dist/surface.d.ts +33 -7
- package/node_modules/@engenty-wizards/shared/dist/surface.js +263 -20
- package/package.json +1 -1
- package/apps/web/dist/assets/AboutDialog-CkE7uZNL.js +0 -1
- package/apps/web/dist/assets/ChatView-DClGzMte.js +0 -10
- package/apps/web/dist/assets/EditorPage-Dg27sIZ7.js +0 -3
- package/apps/web/dist/assets/NewWizardPage-DhDXrjKX.js +0 -7
- package/apps/web/dist/assets/ProjectPage-dvtJn_3c.js +0 -1
- package/apps/web/dist/assets/PublicRunner-lP4sVF1q.js +0 -1
- package/apps/web/dist/assets/RunDrawer-B2bsB9Z6.js +0 -4
- package/apps/web/dist/assets/SettingsPage-C0_wAa_j.js +0 -1
- package/apps/web/dist/assets/SetupPage-kuvBk0G0.js +0 -1
- package/apps/web/dist/assets/SharePage-COLVxXMI.js +0 -1
- package/apps/web/dist/assets/changelog-CIYdRaa5.js +0 -1
- package/apps/web/dist/assets/index-Da9Pvzpj.js +0 -14
- package/apps/web/dist/assets/index-DaKjB676.css +0 -1
- package/apps/web/dist/assets/ui-B9AOCT0v.js +0 -134
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { type ObjectShape } from "./shape.js";
|
|
2
3
|
/**
|
|
3
4
|
* Surfaces: views composed from a small catalog of native components, bound to a run's data and
|
|
4
5
|
* rendered by the runner itself — themed, on phones, no iframe and nothing to pay per run. A
|
|
@@ -8,10 +9,12 @@ import { z } from "zod";
|
|
|
8
9
|
*
|
|
9
10
|
* A surface is a flat list of components with ids; the one with id "root" is drawn, containers
|
|
10
11
|
* name their children by id. A prop may be a literal or `{ "path": "/json/pointer" }` into the
|
|
11
|
-
* surface's data. A `List` or `
|
|
12
|
-
* without a leading slash reads the row ("name"), one with a slash the whole data.
|
|
12
|
+
* surface's data. A `List`, `Table` or `Group` repeats over an array: inside a repeated row, a
|
|
13
|
+
* path without a leading slash reads the row ("name"), one with a slash the whole data. A path
|
|
14
|
+
* may turn what it reads into words: `map` looks the value up (`{ "true": "im Kühlschrank" }`),
|
|
15
|
+
* `format` sets it into a text ("{} Min").
|
|
13
16
|
*/
|
|
14
|
-
export declare const SURFACE_COMPONENTS: readonly ["Column", "Text", "List", "Row", "DetailGrid", "Badge", "Grid", "Metric", "Table", "Image", "BarChart", "LineChart", "DonutChart", "Actions", "Button"];
|
|
17
|
+
export declare const SURFACE_COMPONENTS: readonly ["Column", "Text", "List", "Row", "DetailGrid", "Badge", "Grid", "Metric", "Table", "Image", "BarChart", "LineChart", "DonutChart", "Actions", "Button", "Tabs", "Card", "Fold", "Group", "Chips", "Checklist", "Steps", "Link", "Callout"];
|
|
15
18
|
export type SurfaceComponentName = (typeof SURFACE_COMPONENTS)[number];
|
|
16
19
|
export declare const SURFACE_ACTIONS: readonly ["regenerate", "open"];
|
|
17
20
|
/** One component: its id, its kind, its children (ids, or a template repeated over an array). */
|
|
@@ -22,16 +25,25 @@ export declare const surfaceComponentSchema: z.ZodObject<{
|
|
|
22
25
|
Badge: "Badge";
|
|
23
26
|
BarChart: "BarChart";
|
|
24
27
|
Button: "Button";
|
|
28
|
+
Callout: "Callout";
|
|
29
|
+
Card: "Card";
|
|
30
|
+
Checklist: "Checklist";
|
|
31
|
+
Chips: "Chips";
|
|
25
32
|
Column: "Column";
|
|
26
33
|
DetailGrid: "DetailGrid";
|
|
27
34
|
DonutChart: "DonutChart";
|
|
35
|
+
Fold: "Fold";
|
|
28
36
|
Grid: "Grid";
|
|
37
|
+
Group: "Group";
|
|
29
38
|
Image: "Image";
|
|
30
39
|
LineChart: "LineChart";
|
|
40
|
+
Link: "Link";
|
|
31
41
|
List: "List";
|
|
32
42
|
Metric: "Metric";
|
|
33
43
|
Row: "Row";
|
|
44
|
+
Steps: "Steps";
|
|
34
45
|
Table: "Table";
|
|
46
|
+
Tabs: "Tabs";
|
|
35
47
|
Text: "Text";
|
|
36
48
|
}>;
|
|
37
49
|
children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
|
|
@@ -47,16 +59,25 @@ export declare const surfaceComponentsSchema: z.ZodArray<z.ZodObject<{
|
|
|
47
59
|
Badge: "Badge";
|
|
48
60
|
BarChart: "BarChart";
|
|
49
61
|
Button: "Button";
|
|
62
|
+
Callout: "Callout";
|
|
63
|
+
Card: "Card";
|
|
64
|
+
Checklist: "Checklist";
|
|
65
|
+
Chips: "Chips";
|
|
50
66
|
Column: "Column";
|
|
51
67
|
DetailGrid: "DetailGrid";
|
|
52
68
|
DonutChart: "DonutChart";
|
|
69
|
+
Fold: "Fold";
|
|
53
70
|
Grid: "Grid";
|
|
71
|
+
Group: "Group";
|
|
54
72
|
Image: "Image";
|
|
55
73
|
LineChart: "LineChart";
|
|
74
|
+
Link: "Link";
|
|
56
75
|
List: "List";
|
|
57
76
|
Metric: "Metric";
|
|
58
77
|
Row: "Row";
|
|
78
|
+
Steps: "Steps";
|
|
59
79
|
Table: "Table";
|
|
80
|
+
Tabs: "Tabs";
|
|
60
81
|
Text: "Text";
|
|
61
82
|
}>;
|
|
62
83
|
children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
|
|
@@ -74,10 +95,10 @@ export interface SurfaceIssue {
|
|
|
74
95
|
}
|
|
75
96
|
/**
|
|
76
97
|
* What can be wrong with a surface: an unknown or missing component, no root, a child that is
|
|
77
|
-
* not there, an id twice, a loop, a prop missing, and — given the data keys a run will provide
|
|
78
|
-
*
|
|
98
|
+
* not there, an id twice, a loop, a prop missing, and — given the data keys a run will provide,
|
|
99
|
+
* or the step's schema — a path into data nothing provides.
|
|
79
100
|
*/
|
|
80
|
-
export declare function validateSurface(raw: unknown,
|
|
101
|
+
export declare function validateSurface(raw: unknown, data?: string[] | ObjectShape): SurfaceIssue[];
|
|
81
102
|
/** A JSON pointer into data: "/suppliers/0/name". */
|
|
82
103
|
export declare function pointer(data: unknown, path: string): unknown;
|
|
83
104
|
/**
|
|
@@ -85,5 +106,10 @@ export declare function pointer(data: unknown, path: string): unknown;
|
|
|
85
106
|
* from the row a List or Table repeats over.
|
|
86
107
|
*/
|
|
87
108
|
export declare function bound(value: unknown, data: unknown, row?: unknown): unknown;
|
|
109
|
+
/** A value turned into words as its path says: looked up in `map`, set into `format`. */
|
|
110
|
+
export declare function worded(raw: unknown, spec: {
|
|
111
|
+
map?: unknown;
|
|
112
|
+
format?: unknown;
|
|
113
|
+
}): unknown;
|
|
88
114
|
/** What a model needs to compose a surface: the catalog, briefly. */
|
|
89
|
-
export declare const SURFACE_GUIDE = "A surface is a flat JSON array of components; the one with id \"root\" is drawn. Containers list their children by id.\nComponents and props (a prop may be a literal or {\"path\": \"/key/...\"} into the data):\n- Column { children: [ids] } \u2014 vertical stack (use for root)\n- Text { text, variant?: \"h3\"|\"h4\"|\"body\"|\"muted\" }\n- List { children: {\"path\": \"/rows\", \"componentId\": \"<a Row id>\"} } \u2014 one Row per array entry; inside, paths without \"/\" read the entry (\"name\")\n- Row { title, subtitle?, meta?, badge?, image? }\n- DetailGrid { rows: [{ label, value }] } \u2014 label/value facts\n- Badge { label, tone?: \"default\"|\"success\"|\"warning\" }\n- Grid { children: [ids], columns?: 2|3|4 } \u2014 tiles side by side\n- Metric { label, value, caption? } \u2014 a key figure\n- Table { rows: {\"path\": \"/rows\"}, columns?: [{ key, label }] }\n- Image { src: an asset id or {\"path\": ...}, alt? }\n- BarChart / LineChart { title?, points: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n- DonutChart { title?, slices: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n (labelKey / valueKey: the columns of bound rows that hold the label and the number, e.g. \"name\", \"price\")\n- Actions { children: [Button ids] } / Button { label, action: \"regenerate\"|\"open\" }\nKeep it small: what the person needs to see first, then the details. Never invent numbers: bind them by path.";
|
|
115
|
+
export declare const SURFACE_GUIDE = "A surface is a flat JSON array of components; the one with id \"root\" is drawn. Containers list their children by id.\nComponents and props (a prop may be a literal or {\"path\": \"/key/...\"} into the data):\n- Column { children: [ids] } \u2014 vertical stack (use for root); Column and Grid may also repeat one component per entry: children {\"path\", \"componentId\"}\n- Text { text, variant?: \"h3\"|\"h4\"|\"lead\"|\"body\"|\"muted\" } \u2014 \"lead\": the one opening line in the wizard's voice\n- List { children: {\"path\": \"/rows\", \"componentId\": \"<a Row id>\"} } \u2014 one Row per array entry; inside, paths without \"/\" read the entry (\"name\")\n- Row { title, subtitle?, meta?, badge?, image? }\n- DetailGrid { rows: [{ label, value }] } \u2014 label/value facts\n- Badge { label, tone?: \"default\"|\"success\"|\"warning\"|\"accent\" }\n- Grid { children: [ids], columns?: 2|3|4, min?: rem } \u2014 tiles side by side; min: the narrowest a tile gets (14 for cards, so a phone shows one)\n- Metric { label, value, caption? } \u2014 a key figure\n- Table { rows: {\"path\": \"/rows\"}, columns?: [{ key, label }] }\n- Image { src: an asset id or {\"path\": ...}, alt? }\n- BarChart / LineChart { title?, points: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n- DonutChart { title?, slices: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n (labelKey / valueKey: the columns of bound rows that hold the label and the number, e.g. \"name\", \"price\")\n- Actions { children: [Button ids] } / Button { label, action: \"regenerate\"|\"open\" }\n- Tabs { tabs: [{ label, count?, child: id }] } \u2014 two to four views of one result; count may bind a list (shows its length)\n- Card { title, eyebrow?, subtitle?, meta?: [values], image?, children?: [ids] } \u2014 one thing: a day, a recipe, an offer\n- Fold { title, open?, children: [ids] } \u2014 details that open on a tap\n- Group { children: {\"path\", \"componentId\"}, by: \"<key>\", order?: [values] } \u2014 entries under a heading per value of a key\n- Chips { items, labelKey?, flagKey?, flag? } \u2014 short things at a glance; flagKey marks some (\"bald\")\n- Checklist { items, labelKey?, detailKey?, noteKey?, noteFormat?, noteMap?, groupKey?, groupOrder?, share? } \u2014 things to get or do; ticks are kept; a yes/no note needs noteMap: {\"true\": \"da\", \"false\": \"einkaufen\"}\n- Steps { items, textKey?, minutesKey? } \u2014 ordered work, numbered, with times\n- Link { title, subtitle?, eyebrow?, meta?, look?: \"row\"|\"card\", items: {\"path\": \"/recipes\"}, key?: \"id\", value: {\"path\": \"recipe_id\"}, view: id } \u2014 opens the entry of items whose key is value in a sheet, drawn by view; title, subtitle and meta read that entry, eyebrow the row the Link sits in\n- Callout { text, title?, tone?: \"tip\"|\"note\"|\"warning\" }\nA path may put its value into words: {\"path\": \"in_fridge\", \"map\": {\"true\": \"da\", \"false\": \"einkaufen\"}}, {\"path\": \"minutes\", \"format\": \"{} Min\"}.\nDesign it like an app, not a report: lead with a headline, the key figure or the chips; one Card per thing, never a Table of things; ordered work is Steps, things to get are a Checklist, sets are grouped by their key. A Table only for figures people compare across columns.\nKeep it small: what the person needs to see first, then the details. Never invent numbers: bind them by path.";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: FSL-1.1-MIT OR MIT
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { shapeAt } from "./shape.js";
|
|
3
4
|
/**
|
|
4
5
|
* Surfaces: views composed from a small catalog of native components, bound to a run's data and
|
|
5
6
|
* rendered by the runner itself — themed, on phones, no iframe and nothing to pay per run. A
|
|
@@ -9,8 +10,10 @@ import { z } from "zod";
|
|
|
9
10
|
*
|
|
10
11
|
* A surface is a flat list of components with ids; the one with id "root" is drawn, containers
|
|
11
12
|
* name their children by id. A prop may be a literal or `{ "path": "/json/pointer" }` into the
|
|
12
|
-
* surface's data. A `List` or `
|
|
13
|
-
* without a leading slash reads the row ("name"), one with a slash the whole data.
|
|
13
|
+
* surface's data. A `List`, `Table` or `Group` repeats over an array: inside a repeated row, a
|
|
14
|
+
* path without a leading slash reads the row ("name"), one with a slash the whole data. A path
|
|
15
|
+
* may turn what it reads into words: `map` looks the value up (`{ "true": "im Kühlschrank" }`),
|
|
16
|
+
* `format` sets it into a text ("{} Min").
|
|
14
17
|
*/
|
|
15
18
|
export const SURFACE_COMPONENTS = [
|
|
16
19
|
"Column",
|
|
@@ -28,9 +31,26 @@ export const SURFACE_COMPONENTS = [
|
|
|
28
31
|
"DonutChart",
|
|
29
32
|
"Actions",
|
|
30
33
|
"Button",
|
|
34
|
+
"Tabs",
|
|
35
|
+
"Card",
|
|
36
|
+
"Fold",
|
|
37
|
+
"Group",
|
|
38
|
+
"Chips",
|
|
39
|
+
"Checklist",
|
|
40
|
+
"Steps",
|
|
41
|
+
"Link",
|
|
42
|
+
"Callout",
|
|
31
43
|
];
|
|
32
44
|
/** Components that hold others by id. */
|
|
33
|
-
const CONTAINERS = new Set([
|
|
45
|
+
const CONTAINERS = new Set([
|
|
46
|
+
"Column",
|
|
47
|
+
"List",
|
|
48
|
+
"Grid",
|
|
49
|
+
"Actions",
|
|
50
|
+
"Card",
|
|
51
|
+
"Fold",
|
|
52
|
+
"Group",
|
|
53
|
+
]);
|
|
34
54
|
/** The props each component needs. */
|
|
35
55
|
const REQUIRED = {
|
|
36
56
|
Text: ["text"],
|
|
@@ -44,6 +64,15 @@ const REQUIRED = {
|
|
|
44
64
|
LineChart: ["points"],
|
|
45
65
|
DonutChart: ["slices"],
|
|
46
66
|
Button: ["label", "action"],
|
|
67
|
+
Tabs: ["tabs"],
|
|
68
|
+
Card: ["title"],
|
|
69
|
+
Fold: ["title", "children"],
|
|
70
|
+
Group: ["children", "by"],
|
|
71
|
+
Chips: ["items"],
|
|
72
|
+
Checklist: ["items"],
|
|
73
|
+
Steps: ["items"],
|
|
74
|
+
Link: ["title", "items", "value", "view"],
|
|
75
|
+
Callout: ["text"],
|
|
47
76
|
};
|
|
48
77
|
export const SURFACE_ACTIONS = ["regenerate", "open"];
|
|
49
78
|
const id = z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,40}$/, "ids are letters, digits, _ and -");
|
|
@@ -57,6 +86,24 @@ export const surfaceComponentSchema = z.looseObject({
|
|
|
57
86
|
});
|
|
58
87
|
export const surfaceComponentsSchema = z.array(surfaceComponentSchema).min(1).max(200);
|
|
59
88
|
const isPath = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v) && typeof v.path === "string");
|
|
89
|
+
/**
|
|
90
|
+
* The ids a component draws: its children, the views of its tabs. A Link's view is drawn only
|
|
91
|
+
* when it is opened, so it is no part of the tree.
|
|
92
|
+
*/
|
|
93
|
+
function childIds(c) {
|
|
94
|
+
const kids = c.children;
|
|
95
|
+
const ids = Array.isArray(kids) ? [...kids] : kids ? [kids.componentId] : [];
|
|
96
|
+
const tabs = c.tabs;
|
|
97
|
+
if (Array.isArray(tabs)) {
|
|
98
|
+
for (const tab of tabs) {
|
|
99
|
+
const child = tab?.child;
|
|
100
|
+
if (typeof child === "string") {
|
|
101
|
+
ids.push(child);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return ids;
|
|
106
|
+
}
|
|
60
107
|
/** Every `{ path }` in a component's props, with whether it reads a repeated row. */
|
|
61
108
|
function pathsOf(c) {
|
|
62
109
|
const out = [];
|
|
@@ -78,12 +125,173 @@ function pathsOf(c) {
|
|
|
78
125
|
}
|
|
79
126
|
return out;
|
|
80
127
|
}
|
|
128
|
+
/** Props naming a key of the entries a component's `items` (or chart's points) holds. */
|
|
129
|
+
const ENTRY_KEYS = [
|
|
130
|
+
"labelKey",
|
|
131
|
+
"valueKey",
|
|
132
|
+
"flagKey",
|
|
133
|
+
"detailKey",
|
|
134
|
+
"noteKey",
|
|
135
|
+
"groupKey",
|
|
136
|
+
"textKey",
|
|
137
|
+
"minutesKey",
|
|
138
|
+
];
|
|
139
|
+
/** A path as parts: "/days/0/label" from the data, "meals.slot" from the entry. */
|
|
140
|
+
const partsOf = (path) => (path.startsWith("/") ? path.slice(1) : path)
|
|
141
|
+
.split(/[./]/)
|
|
142
|
+
.filter(Boolean)
|
|
143
|
+
.map((p) => p.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
144
|
+
/**
|
|
145
|
+
* The paths a surface reads, followed through the step's schema from "root": a repeated child
|
|
146
|
+
* reads an entry of the list its path names, a Link's view the entry it opens. Every path has to
|
|
147
|
+
* be in the schema, every key a component names in its entries.
|
|
148
|
+
*/
|
|
149
|
+
function shapeIssues(byId, root) {
|
|
150
|
+
const issues = [];
|
|
151
|
+
const seen = new Map();
|
|
152
|
+
/** The shape a path reads where `entry` is drawn; "any": unchecked. */
|
|
153
|
+
const resolve = (path, entry) => {
|
|
154
|
+
if (path.startsWith("/")) {
|
|
155
|
+
return shapeAt(root, partsOf(path));
|
|
156
|
+
}
|
|
157
|
+
if (entry === "any") {
|
|
158
|
+
return "any";
|
|
159
|
+
}
|
|
160
|
+
return entry ? shapeAt(entry, partsOf(path)) : undefined;
|
|
161
|
+
};
|
|
162
|
+
const say = (c, path, entry) => issues.push({
|
|
163
|
+
message: !path.startsWith("/") && !entry
|
|
164
|
+
? `"${c.id}" reads "${path}" outside a repeated entry; from the data it is "/${path.replace(/\./g, "/")}".`
|
|
165
|
+
: `"${c.id}" reads "${path}", which no data provides.`,
|
|
166
|
+
});
|
|
167
|
+
/** The entries of a list a prop binds, or undefined (and an issue) where it is no list. */
|
|
168
|
+
const entriesOf = (c, value, entry) => {
|
|
169
|
+
if (!isPath(value)) {
|
|
170
|
+
return "any";
|
|
171
|
+
}
|
|
172
|
+
const at = resolve(value.path, entry);
|
|
173
|
+
if (at === "any") {
|
|
174
|
+
return "any";
|
|
175
|
+
}
|
|
176
|
+
if (at?.kind === "list") {
|
|
177
|
+
return at.of;
|
|
178
|
+
}
|
|
179
|
+
if (at?.kind === "table") {
|
|
180
|
+
return at.columns?.length
|
|
181
|
+
? {
|
|
182
|
+
kind: "object",
|
|
183
|
+
fields: Object.fromEntries(at.columns.map((k) => [k, { kind: "text" }])),
|
|
184
|
+
}
|
|
185
|
+
: "any";
|
|
186
|
+
}
|
|
187
|
+
if (at) {
|
|
188
|
+
issues.push({ message: `"${c.id}" reads "${value.path}" as a list; it is ${at.kind}.` });
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
say(c, value.path, entry);
|
|
192
|
+
}
|
|
193
|
+
return undefined;
|
|
194
|
+
};
|
|
195
|
+
const hasKey = (shape, k) => shape === "any" || shape === undefined || shape.kind !== "object" || k in shape.fields;
|
|
196
|
+
const visit = (cid, entry) => {
|
|
197
|
+
const c = byId.get(cid);
|
|
198
|
+
const done = seen.get(cid) ?? new Set();
|
|
199
|
+
if (!c || done.has(entry)) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
done.add(entry);
|
|
203
|
+
seen.set(cid, done);
|
|
204
|
+
const props = c;
|
|
205
|
+
// What the component's items, rows or points hold, for the keys it names in them.
|
|
206
|
+
const listProp = ["items", "rows", "points", "slices"].find((k) => isPath(props[k]));
|
|
207
|
+
const items = listProp ? entriesOf(c, props[listProp], entry) : undefined;
|
|
208
|
+
for (const k of ENTRY_KEYS) {
|
|
209
|
+
const named = props[k];
|
|
210
|
+
if (typeof named === "string" && items && !hasKey(items, named)) {
|
|
211
|
+
issues.push({
|
|
212
|
+
message: `"${c.id}": "${k}" names "${named}", which its entries do not have.`,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (c.component === "Table" && Array.isArray(props.columns) && items) {
|
|
217
|
+
for (const col of props.columns) {
|
|
218
|
+
if (typeof col?.key === "string" && !hasKey(items, col.key)) {
|
|
219
|
+
issues.push({ message: `"${c.id}": no column "${col.key}" in its rows.` });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// A Link: title, subtitle and meta read the entry it opens, the rest the entry it sits in.
|
|
224
|
+
const opened = c.component === "Link" ? items : undefined;
|
|
225
|
+
if (c.component === "Link" && typeof props.key === "string" && !hasKey(opened, props.key)) {
|
|
226
|
+
issues.push({ message: `"${c.id}": its items have no "${props.key}".` });
|
|
227
|
+
}
|
|
228
|
+
for (const [k, value] of Object.entries(props)) {
|
|
229
|
+
if (k === "id" || k === "component" || k === "children" || k === listProp) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const reads = c.component === "Link" && (k === "title" || k === "subtitle" || k === "meta");
|
|
233
|
+
const scope = reads ? opened : entry;
|
|
234
|
+
const paths = [];
|
|
235
|
+
const walk = (v) => {
|
|
236
|
+
if (isPath(v)) {
|
|
237
|
+
paths.push(v.path);
|
|
238
|
+
}
|
|
239
|
+
else if (Array.isArray(v)) {
|
|
240
|
+
v.forEach(walk);
|
|
241
|
+
}
|
|
242
|
+
else if (v && typeof v === "object") {
|
|
243
|
+
Object.values(v).forEach(walk);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
walk(value);
|
|
247
|
+
for (const path of paths) {
|
|
248
|
+
if (resolve(path, scope) === undefined) {
|
|
249
|
+
say(c, path, scope);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const kids = c.children;
|
|
254
|
+
if (Array.isArray(kids)) {
|
|
255
|
+
for (const k of kids) {
|
|
256
|
+
visit(k, entry);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else if (kids) {
|
|
260
|
+
const of = entriesOf(c, { path: kids.path }, entry);
|
|
261
|
+
if (of !== undefined) {
|
|
262
|
+
if (c.component === "Group" && typeof props.by === "string" && !hasKey(of, props.by)) {
|
|
263
|
+
issues.push({
|
|
264
|
+
message: `"${c.id}": "by" names "${props.by}", which its entries do not have.`,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
visit(kids.componentId, of);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const tabs = props.tabs;
|
|
271
|
+
if (Array.isArray(tabs)) {
|
|
272
|
+
for (const tab of tabs) {
|
|
273
|
+
const child = tab?.child;
|
|
274
|
+
if (typeof child === "string") {
|
|
275
|
+
visit(child, entry);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (c.component === "Link" && typeof props.view === "string" && opened !== undefined) {
|
|
280
|
+
visit(props.view, opened);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
if (byId.has("root")) {
|
|
284
|
+
visit("root", undefined);
|
|
285
|
+
}
|
|
286
|
+
return issues;
|
|
287
|
+
}
|
|
81
288
|
/**
|
|
82
289
|
* What can be wrong with a surface: an unknown or missing component, no root, a child that is
|
|
83
|
-
* not there, an id twice, a loop, a prop missing, and — given the data keys a run will provide
|
|
84
|
-
*
|
|
290
|
+
* not there, an id twice, a loop, a prop missing, and — given the data keys a run will provide,
|
|
291
|
+
* or the step's schema — a path into data nothing provides.
|
|
85
292
|
*/
|
|
86
|
-
export function validateSurface(raw,
|
|
293
|
+
export function validateSurface(raw, data) {
|
|
294
|
+
const dataKeys = Array.isArray(data) ? data : undefined;
|
|
87
295
|
const parsed = surfaceComponentsSchema.safeParse(raw);
|
|
88
296
|
if (!parsed.success) {
|
|
89
297
|
return parsed.error.issues.map((i) => ({ message: `${i.path.join(".")}: ${i.message}` }));
|
|
@@ -116,7 +324,17 @@ export function validateSurface(raw, dataKeys) {
|
|
|
116
324
|
if (children && !CONTAINERS.has(c.component) && c.component !== "Table") {
|
|
117
325
|
issues.push({ message: `${c.component} "${c.id}" holds no children.` });
|
|
118
326
|
}
|
|
119
|
-
|
|
327
|
+
if (c.component === "Group" && (!children || Array.isArray(children))) {
|
|
328
|
+
issues.push({
|
|
329
|
+
message: `Group "${c.id}" repeats over a list: children { "path", "componentId" }.`,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
const tabs = c.tabs;
|
|
333
|
+
if (c.component === "Tabs" && !(Array.isArray(tabs) && tabs.length >= 2)) {
|
|
334
|
+
issues.push({ message: `Tabs "${c.id}" needs at least two tabs: [{ label, child }].` });
|
|
335
|
+
}
|
|
336
|
+
const view = c.view;
|
|
337
|
+
const ids = [...childIds(c), ...(typeof view === "string" ? [view] : [])];
|
|
120
338
|
for (const child of ids) {
|
|
121
339
|
if (!byId.has(child)) {
|
|
122
340
|
issues.push({ message: `"${c.id}" names a child "${child}" that is not there.` });
|
|
@@ -142,18 +360,15 @@ export function validateSurface(raw, dataKeys) {
|
|
|
142
360
|
}
|
|
143
361
|
seen.add(cid);
|
|
144
362
|
const c = byId.get(cid);
|
|
145
|
-
const kids =
|
|
146
|
-
? c.children
|
|
147
|
-
: c?.children
|
|
148
|
-
? [c.children.componentId]
|
|
149
|
-
: [];
|
|
363
|
+
const kids = c ? childIds(c) : [];
|
|
150
364
|
const next = new Set(stack).add(cid);
|
|
151
365
|
return kids.some((k) => loops(k, next));
|
|
152
366
|
};
|
|
153
367
|
if (byId.has("root") && loops("root", new Set())) {
|
|
154
368
|
issues.push({ message: "Components hold each other in a loop." });
|
|
369
|
+
return issues;
|
|
155
370
|
}
|
|
156
|
-
return issues;
|
|
371
|
+
return data && !Array.isArray(data) ? [...issues, ...shapeIssues(byId, data)] : issues;
|
|
157
372
|
}
|
|
158
373
|
/** A JSON pointer into data: "/suppliers/0/name". */
|
|
159
374
|
export function pointer(data, path) {
|
|
@@ -174,21 +389,38 @@ export function bound(value, data, row) {
|
|
|
174
389
|
if (!isPath(value)) {
|
|
175
390
|
return value;
|
|
176
391
|
}
|
|
177
|
-
|
|
178
|
-
|
|
392
|
+
const raw = value.path.startsWith("/")
|
|
393
|
+
? pointer(data, value.path)
|
|
394
|
+
: row === undefined
|
|
395
|
+
? undefined
|
|
396
|
+
: pointer(row, `/${value.path.replace(/\./g, "/")}`);
|
|
397
|
+
return worded(raw, value);
|
|
398
|
+
}
|
|
399
|
+
/** A value turned into words as its path says: looked up in `map`, set into `format`. */
|
|
400
|
+
export function worded(raw, spec) {
|
|
401
|
+
let v = raw;
|
|
402
|
+
const map = spec.map;
|
|
403
|
+
if (map && typeof map === "object" && !Array.isArray(map)) {
|
|
404
|
+
const key = String(v);
|
|
405
|
+
if (Object.hasOwn(map, key)) {
|
|
406
|
+
v = map[key];
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
if (typeof spec.format === "string" && v !== undefined && v !== null && v !== "") {
|
|
410
|
+
v = spec.format.replace("{}", Array.isArray(v) ? v.join(", ") : String(v));
|
|
179
411
|
}
|
|
180
|
-
return
|
|
412
|
+
return v;
|
|
181
413
|
}
|
|
182
414
|
/** What a model needs to compose a surface: the catalog, briefly. */
|
|
183
415
|
export const SURFACE_GUIDE = `A surface is a flat JSON array of components; the one with id "root" is drawn. Containers list their children by id.
|
|
184
416
|
Components and props (a prop may be a literal or {"path": "/key/..."} into the data):
|
|
185
|
-
- Column { children: [ids] } — vertical stack (use for root)
|
|
186
|
-
- Text { text, variant?: "h3"|"h4"|"body"|"muted" }
|
|
417
|
+
- Column { children: [ids] } — vertical stack (use for root); Column and Grid may also repeat one component per entry: children {"path", "componentId"}
|
|
418
|
+
- Text { text, variant?: "h3"|"h4"|"lead"|"body"|"muted" } — "lead": the one opening line in the wizard's voice
|
|
187
419
|
- List { children: {"path": "/rows", "componentId": "<a Row id>"} } — one Row per array entry; inside, paths without "/" read the entry ("name")
|
|
188
420
|
- Row { title, subtitle?, meta?, badge?, image? }
|
|
189
421
|
- DetailGrid { rows: [{ label, value }] } — label/value facts
|
|
190
|
-
- Badge { label, tone?: "default"|"success"|"warning" }
|
|
191
|
-
- Grid { children: [ids], columns?: 2|3|4 } — tiles side by side
|
|
422
|
+
- Badge { label, tone?: "default"|"success"|"warning"|"accent" }
|
|
423
|
+
- Grid { children: [ids], columns?: 2|3|4, min?: rem } — tiles side by side; min: the narrowest a tile gets (14 for cards, so a phone shows one)
|
|
192
424
|
- Metric { label, value, caption? } — a key figure
|
|
193
425
|
- Table { rows: {"path": "/rows"}, columns?: [{ key, label }] }
|
|
194
426
|
- Image { src: an asset id or {"path": ...}, alt? }
|
|
@@ -196,4 +428,15 @@ Components and props (a prop may be a literal or {"path": "/key/..."} into the d
|
|
|
196
428
|
- DonutChart { title?, slices: [{ label, value }] or {"path": ...}, labelKey?, valueKey? }
|
|
197
429
|
(labelKey / valueKey: the columns of bound rows that hold the label and the number, e.g. "name", "price")
|
|
198
430
|
- Actions { children: [Button ids] } / Button { label, action: "regenerate"|"open" }
|
|
431
|
+
- Tabs { tabs: [{ label, count?, child: id }] } — two to four views of one result; count may bind a list (shows its length)
|
|
432
|
+
- Card { title, eyebrow?, subtitle?, meta?: [values], image?, children?: [ids] } — one thing: a day, a recipe, an offer
|
|
433
|
+
- Fold { title, open?, children: [ids] } — details that open on a tap
|
|
434
|
+
- Group { children: {"path", "componentId"}, by: "<key>", order?: [values] } — entries under a heading per value of a key
|
|
435
|
+
- Chips { items, labelKey?, flagKey?, flag? } — short things at a glance; flagKey marks some ("bald")
|
|
436
|
+
- Checklist { items, labelKey?, detailKey?, noteKey?, noteFormat?, noteMap?, groupKey?, groupOrder?, share? } — things to get or do; ticks are kept; a yes/no note needs noteMap: {"true": "da", "false": "einkaufen"}
|
|
437
|
+
- Steps { items, textKey?, minutesKey? } — ordered work, numbered, with times
|
|
438
|
+
- Link { title, subtitle?, eyebrow?, meta?, look?: "row"|"card", items: {"path": "/recipes"}, key?: "id", value: {"path": "recipe_id"}, view: id } — opens the entry of items whose key is value in a sheet, drawn by view; title, subtitle and meta read that entry, eyebrow the row the Link sits in
|
|
439
|
+
- Callout { text, title?, tone?: "tip"|"note"|"warning" }
|
|
440
|
+
A path may put its value into words: {"path": "in_fridge", "map": {"true": "da", "false": "einkaufen"}}, {"path": "minutes", "format": "{} Min"}.
|
|
441
|
+
Design it like an app, not a report: lead with a headline, the key figure or the chips; one Card per thing, never a Table of things; ordered work is Steps, things to get are a Checklist, sets are grouped by their key. A Table only for figures people compare across columns.
|
|
199
442
|
Keep it small: what the person needs to see first, then the details. Never invent numbers: bind them by path.`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wizards",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Make a wish. Get your wizard. It guides you step by step. Let AI do the work. Runs on your machine, on the AI subscription you already have.",
|
|
5
5
|
"license": "FSL-1.1-MIT",
|
|
6
6
|
"homepage": "https://engenty.ai",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{$n as r,An as i,At as a,Mt as o,Nt as s,Rt as c,Ut as l,Vt as u,Xt as d,ir as f,jt as p}from"./ui-B9AOCT0v.js";import{t as m}from"./preload-helper-CNEI7N0N.js";import{G as h,U as g,W as _,bt as v}from"./index-Da9Pvzpj.js";import{c as y,f as b}from"./settings-menu-B7eXkvba.js";import{ReleaseNotes as x,loadReleases as S,releaseDate as C,releaseLabel as w}from"./ChangelogDialog-BCS3WIRA.js";var T=e(t(),1),E=[{name:`engenty wizards`,description:`credit.engenty-wizards`,homepage:`https://github.com/engenty/wizards`,license:`FSL-1.1-MIT`},{name:`engenty`,description:`credit.engenty`,homepage:`https://github.com/engenty/engenty`,license:`FSL-1.1-MIT`}],D=[{name:`Mastra`,description:`credit.mastra`,homepage:`https://github.com/mastra-ai/mastra`,license:`Apache-2.0`},{name:`AI SDK`,description:`credit.ai-sdk`,homepage:`https://github.com/vercel/ai`,license:`Apache-2.0`},{name:`Model Context Protocol`,description:`credit.model-context-protocol`,homepage:`https://github.com/modelcontextprotocol/typescript-sdk`,license:`MIT`},{name:`Hono`,description:`credit.hono`,homepage:`https://github.com/honojs/hono`,license:`MIT`},{name:`Drizzle ORM`,description:`credit.drizzle-orm`,homepage:`https://github.com/drizzle-team/drizzle-orm`,license:`Apache-2.0`},{name:`libSQL`,description:`credit.libsql`,homepage:`https://github.com/tursodatabase/libsql`,license:`MIT`},{name:`Playwright`,description:`credit.playwright`,homepage:`https://github.com/microsoft/playwright`,license:`Apache-2.0`},{name:`agentOS`,description:`credit.agentos`,homepage:`https://github.com/rivet-dev/agentos`,license:`Apache-2.0`},{name:`React`,description:`credit.react`,homepage:`https://github.com/facebook/react`,license:`MIT`},{name:`Vite`,description:`credit.vite`,homepage:`https://github.com/vitejs/vite`,license:`MIT`},{name:`Tailwind CSS`,description:`credit.tailwind-css`,homepage:`https://github.com/tailwindlabs/tailwindcss`,license:`MIT`},{name:`React Flow`,description:`credit.react-flow`,homepage:`https://github.com/xyflow/xyflow`,license:`MIT`},{name:`TanStack Query`,description:`credit.tanstack-query`,homepage:`https://github.com/TanStack/query`,license:`MIT`},{name:`xterm.js`,description:`credit.xterm-js`,homepage:`https://github.com/xtermjs/xterm.js`,license:`MIT`},{name:`Lucide`,description:`credit.lucide`,homepage:`https://github.com/lucide-icons/lucide`,license:`ISC`},{name:`Geist & Geist Mono`,description:`credit.geist-geist-mono`,homepage:`https://github.com/vercel/geist-font`,license:`OFL-1.1`},{name:`Space Grotesk`,description:`credit.space-grotesk`,homepage:`https://github.com/floriankarsten/space-grotesk`,license:`OFL-1.1`},{name:`git-cliff`,description:`credit.git-cliff`,homepage:`https://github.com/orhun/git-cliff`,license:`MIT OR Apache-2.0`}],O=e(n(),1),k=(e,...t)=>t.some(t=>t?.toLowerCase().includes(e));function A({name:e,homepage:t,version:n,license:i,description:a}){return(0,O.jsxs)(`li`,{className:`py-2.5`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2.5 gap-y-0.5`,children:[t?(0,O.jsxs)(`a`,{href:t,target:`_blank`,rel:`noreferrer`,className:`inline-flex items-center gap-1 font-medium text-[0.875rem] text-ink underline-offset-4 hover:underline`,children:[e,(0,O.jsx)(r,{"aria-hidden":!0,className:`size-3 text-ink-4`})]}):(0,O.jsx)(`span`,{className:`font-medium text-[0.875rem] text-ink`,children:e}),n?(0,O.jsx)(`span`,{className:`text-[0.75rem] text-ink-3 tabular-nums`,children:n}):null,(0,O.jsx)(`span`,{className:`text-[0.75rem] text-ink-3`,children:i})]}),a?(0,O.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:a}):null]})}function j({title:e,hint:t,children:n}){return(0,O.jsxs)(`section`,{className:`mt-6`,children:[(0,O.jsx)(`h3`,{className:`border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:e}),t?(0,O.jsx)(`p`,{className:`mt-2 text-[0.8125rem] text-ink-3`,children:t}):null,n]})}function M({credits:e}){return(0,O.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:e.map(e=>(0,O.jsx)(A,{name:e.name,homepage:e.homepage,license:e.license,description:d(e.description)},e.name))})}function N({label:e,packages:t}){return(0,O.jsxs)(`div`,{className:`mt-4`,children:[(0,O.jsx)(`h4`,{className:`font-medium text-[0.75rem] text-ink-3 tracking-wide`,children:e}),(0,O.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:t.map(e=>(0,O.jsx)(A,{...e},e.name))})]})}function P({active:e}){let[t,n]=(0,T.useState)(null),[r,i]=(0,T.useState)(``);(0,T.useEffect)(()=>{if(!e||t)return;let r=!1;return m(()=>import(`./oss-credits-BJrR7BR1.js`).then(e=>{r||n(e.default)}),[]),()=>{r=!0}},[e,t]),(0,T.useEffect)(()=>{e||i(``)},[e]);let a=r.trim().toLowerCase(),o=e=>a?e.filter(e=>k(a,e.name,e.license,d(e.description))):e,l=e=>a?e.filter(e=>k(a,e.name,e.license,e.version)):e,u=o(E),f=o(D),h=t?[{id:`shared`,label:d(`about.creditsShared`),packages:l(t.shared)},...t.groups.map(e=>({id:e.id,label:e.label,packages:l(e.packages)}))].filter(e=>e.packages.length>0):[],g=u.length===0&&f.length===0&&h.length===0;return(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(`p`,{className:`mb-4 text-[0.875rem] text-ink-3`,children:d(`about.creditsHint`)}),(0,O.jsx)(s,{type:`search`,value:r,placeholder:d(`about.search`),onChange:e=>i(e.target.value)}),u.length>0?(0,O.jsx)(j,{title:d(`about.creditsProduct`),children:(0,O.jsx)(M,{credits:u})}):null,f.length>0?(0,O.jsx)(j,{title:d(`about.creditsBuiltWith`),children:(0,O.jsx)(M,{credits:f})}):null,t===null?(0,O.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,O.jsx)(c,{})}):h.length>0?(0,O.jsx)(j,{title:d(`about.creditsDeps`),hint:a?void 0:d(`about.creditsDepsHint`),children:h.map(e=>(0,O.jsx)(N,{label:e.label,packages:e.packages},e.id))}):null,t!==null&&g?(0,O.jsx)(p,{children:d(`about.noMatches`)}):null]})}var F=[`new`,`earlier`,`credits`],I=e=>d(e===`new`?`about.tab.new`:e===`earlier`?`about.tab.earlier`:`about.credits`),L=e=>e===1?d(`about.change`):d(`about.changes`,{n:e});function R({open:e,onClose:t,me:n}){let r=n?.mode===`local`,{data:s,latest:p}=h(r&&e),[m,E]=(0,T.useState)(null),[D,k]=(0,T.useState)(`new`),A=b(F.indexOf(D)),j=s?.newer&&p?p:_;(0,T.useEffect)(()=>{if(!e)return;let t=!1;return E(null),S(j===`0.5.13`?void 0:j).then(e=>{t||E(e)}),()=>{t=!0}},[e,j]);let M=m?.find(e=>e.version===`v${j}`)??m?.[0]??null,N=m?.filter(e=>e!==M)??[],R=r?s?.kind??null:`cloud`;return(0,O.jsxs)(a,{open:e,onClose:t,wide:!0,height:`tall`,children:[(0,O.jsx)(`div`,{className:`-mt-2 -mr-2 sticky top-0 z-10 flex h-0 justify-end`,children:(0,O.jsx)(o,{label:d(`common.close`),onClick:t,children:(0,O.jsx)(i,{className:`size-4`})})}),(0,O.jsxs)(`div`,{className:`flex flex-col items-center pt-4 text-center`,children:[(0,O.jsx)(v,{size:96}),(0,O.jsxs)(`div`,{className:`mt-4 font-display font-semibold text-[1.5rem] tracking-tight`,children:[`engenty`,(0,O.jsx)(`span`,{className:`text-ember`,children:`.`}),(0,O.jsx)(`span`,{className:`ml-1.5 font-normal text-ink-3`,children:`wizards`})]}),(0,O.jsxs)(`div`,{className:`mt-1 text-[0.9375rem] text-ink-3 tabular-nums`,children:[d(`about.version`,{v:_}),R?` · ${d(`about.kind.${R}`)}`:``]})]}),r?(0,O.jsx)(`div`,{className:`mt-5`,children:(0,O.jsx)(g,{enabled:e})}):null,(0,O.jsx)(`div`,{className:`mt-6 flex justify-center`,children:(0,O.jsx)(u,{value:D,onChange:k,options:F.map(e=>({id:e,label:I(e)})),label:d(`about.title`)})}),(0,O.jsxs)(`div`,{className:l(`mt-5`,y(A)),children:[D===`new`?m===null?(0,O.jsx)(`div`,{className:`flex justify-center py-6 text-ink-3`,children:(0,O.jsx)(c,{})}):M?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:[w(M),(0,O.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] text-ink-3 tabular-nums`,children:C(M)})]}),(0,O.jsx)(`div`,{className:`mt-3`,children:(0,O.jsx)(x,{release:M})})]}):(0,O.jsx)(`p`,{className:`text-[0.875rem] text-ink-3`,children:d(`about.changelogEmpty`)}):null,D===`earlier`?(0,O.jsx)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:N.map(e=>(0,O.jsxs)(`details`,{className:`group/r py-2`,children:[(0,O.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-baseline gap-3 text-[0.875rem] [&::-webkit-details-marker]:hidden`,children:[(0,O.jsx)(f,{className:`size-3.5 shrink-0 self-center text-ink-4 transition group-open/r:rotate-90`}),(0,O.jsx)(`span`,{className:`font-medium text-ink tabular-nums`,children:w(e)}),(0,O.jsx)(`span`,{className:`text-[0.8125rem] text-ink-3 tabular-nums`,children:C(e)}),(0,O.jsx)(`span`,{className:`ml-auto text-[0.8125rem] text-ink-4`,children:L(e.commits.length)})]}),(0,O.jsx)(`div`,{className:`mt-2 pl-6`,children:(0,O.jsx)(x,{release:e})})]},e.version??`unreleased`))}):null,D===`credits`?(0,O.jsx)(P,{active:!0}):null]},D)]})}export{R as AboutDialog};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{$ as r,$t as i,Fn as a,Ft as o,Gt as s,Ht as c,Kn as l,Ln as u,Mt as d,Nn as f,On as p,Pn as m,Rt as h,Ut as g,Vn as _,W as v,Wn as y,Wt as b,Xt as x,_t as S,bn as C,dt as w,ft as T,gt as E,ht as D,jn as O,lr as k,lt as A,mt as j,nt as M,p as N,pr as P,pt as F,rt as I,sn as L,sr as R,st as z,tt as B,ut as V,vt as ee,wr as te}from"./ui-B9AOCT0v.js";import{t as ne}from"./phone-Dip_wSUZ.js";import{$ as re,Ft as ie,Mt as ae,Q as oe,St as se,Z as ce,ht as le,t as ue}from"./index-Da9Pvzpj.js";import{n as de}from"./RunnerView-BZ83HUnO.js";var fe={name:`hand`,size:24,node:[[`path`,{d:`M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2`,key:`1fvzgz`}],[`path`,{d:`M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2`,key:`1kc0my`}],[`path`,{d:`M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8`,key:`10h0bg`}],[`path`,{d:`M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15`,key:`1s1gnw`}]]};fe.node;var pe=P(fe),me={name:`undo-2`,size:24,node:[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]};me.node;var he=P(me),ge={name:`video-off`,size:24,node:[[`path`,{d:`M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196`,key:`w8jjjt`}],[`path`,{d:`M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2`,key:`1xawa7`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]};ge.node;var _e=P(ge),ve={name:`volume-x`,size:24,node:[[`path`,{d:`M11 4.702a.7.7 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.7.7 0 0 0 11 19.298z`,key:`1p7khw`}],[`path`,{d:`m16.5 14.5 5-5`,key:`cul3yw`}],[`path`,{d:`m16.5 9.5 5 5`,key:`1akey5`}]]};ve.node;var ye=P(ve),be=te(),H=e(t(),1),U=e(n(),1),xe=typeof window<`u`&&window.matchMedia(`(pointer: coarse)`).matches;function Se({since:e}){let[t,n]=(0,H.useState)(Date.now());if((0,H.useEffect)(()=>{if(!e)return;let t=setInterval(()=>n(Date.now()),1e3);return()=>clearInterval(t)},[e]),!e)return null;let r=Math.max(0,Math.floor((t-e)/1e3)),i=String(Math.floor(r/60)).padStart(2,`0`),a=String(r%60).padStart(2,`0`);return(0,U.jsxs)(`span`,{className:`font-mono text-[0.8125rem] text-white/60 tabular-nums`,children:[i,`:`,a]})}function W({label:e,on:t,danger:n,busy:r,onClick:i,children:a}){return(0,U.jsx)(`button`,{type:`button`,"aria-label":e,title:e,"aria-pressed":t,disabled:r,onClick:i,className:g(`flex size-12 items-center justify-center rounded-full transition disabled:opacity-50`,n?`bg-rose text-white hover:brightness-110`:t===!1?`bg-white text-neutral-900 hover:bg-white/90`:`bg-white/15 text-white hover:bg-white/25`),children:r?(0,U.jsx)(h,{className:`size-5`}):a})}function Ce({voice:e}){let t=(0,H.useRef)(null),{captions:n}=e;return(0,H.useEffect)(()=>{n.length&&t.current?.scrollIntoView({block:`end`})},[n]),n.length?(0,U.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 sm:px-5`,children:(0,U.jsxs)(`ol`,{className:`mx-auto flex max-w-[720px] flex-col gap-2 py-2`,children:[n.map(e=>(0,U.jsx)(`li`,{className:g(`text-[0.9375rem] leading-snug`,e.who===`bot`?`text-white/95`:`text-right text-white/50`),children:e.text},e.id)),(0,U.jsx)(`div`,{ref:t})]})}):null}function we({voice:e,view:t,video:n,className:r}){let i=e.state===`live`,a=e.state===`connecting`,[o,s]=(0,H.useState)(null),[c,u]=(0,H.useState)(!1);(0,H.useEffect)(()=>{s(i?Date.now():null)},[i]);let d=async()=>{u(!1),await e.start(),n&&await e.startCamera()},p=()=>{e.stop(),u(!0)},m=n||e.camera,_=[...e.captions].reverse().find(e=>e.who===`bot`),v=[...e.captions].reverse().find(e=>e.who===`me`),y=e.speaking?x(`talk.speaking`):e.listening?x(`talk.listening`):i?x(`talk.live`):a?x(`talk.connecting`):c?x(`video.ended`):``;return(0,U.jsxs)(`section`,{className:g(`relative flex min-h-0 flex-col bg-neutral-950 text-white`,`safe-top`,r),children:[(0,U.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 px-4 sm:px-5`,children:[(0,U.jsx)(`div`,{className:`min-w-0 flex-1 truncate font-display font-semibold text-[1rem] tracking-tight`,children:t?.wizard.title??``}),y?(0,U.jsxs)(`span`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-white/70`,children:[i?(0,U.jsx)(`span`,{className:g(`size-2 rounded-full`,e.speaking?`animate-pulse-dot bg-emerald-400`:`bg-rose`)}):null,y]}):null,(0,U.jsx)(Se,{since:o})]}),(0,U.jsxs)(`div`,{className:g(`grid min-h-0 gap-2 px-3 pb-2 sm:px-4`,m?`flex-1 grid-cols-1 sm:grid-cols-2`:`shrink-0 grid-cols-1`,!m&&i&&e.captions.length?`h-[38%]`:m?``:`flex-1`),children:[(0,U.jsxs)(`div`,{className:g(`relative min-h-0 overflow-hidden rounded-2xl bg-neutral-900`,!m&&`hidden`),children:[(0,U.jsx)(`video`,{ref:e.video,muted:!0,playsInline:!0,autoPlay:!0,className:g(`absolute inset-0 h-full w-full object-cover`,e.facing===`user`&&`-scale-x-100`,e.camera?`block`:`hidden`)}),e.camera?null:(0,U.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/50`,children:[(0,U.jsx)(_e,{className:`size-8`}),(0,U.jsx)(`span`,{className:`text-[0.8125rem]`,children:x(`video.cameraOff`)})]}),(0,U.jsxs)(`span`,{className:`absolute bottom-2 left-3 rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:[x(`video.you`),e.muted?(0,U.jsx)(ie,{className:`ml-1.5 inline size-3`}):null]})]}),(0,U.jsxs)(`div`,{className:g(`relative flex min-h-0 items-center justify-center overflow-hidden rounded-2xl transition-shadow`,m?`bg-neutral-900`:`bg-transparent`,m&&e.speaking&&`ring-2 ring-emerald-400/70`),children:[(0,U.jsx)(`div`,{className:g(`rounded-full transition-shadow duration-500`,!m&&e.listening&&`shadow-[0_0_80px_20px_rgba(244,63,94,0.25)]`,!m&&e.speaking&&`shadow-[0_0_80px_20px_rgba(52,211,153,0.3)]`,e.speaking&&`animate-breathe`),children:(0,U.jsx)(le,{kind:t?.wizard.avatar??`round`,size:m?140:200,fluffy:!0,interactive:!1})}),m?(0,U.jsx)(`span`,{className:`absolute bottom-2 left-3 max-w-[85%] truncate rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:t?.wizard.title??``}):null]})]}),i&&!m?(0,U.jsx)(Ce,{voice:e}):i&&(_||v)?(0,U.jsx)(`div`,{className:`shrink-0 px-4 pb-2 sm:px-5`,children:(0,U.jsxs)(`div`,{className:`mx-auto max-w-[720px] space-y-1 text-center`,children:[v?(0,U.jsx)(`p`,{className:`line-clamp-1 text-[0.8125rem] text-white/50`,children:v.text}):null,_?(0,U.jsx)(`p`,{className:`line-clamp-3 text-[0.9375rem] text-white/95 leading-snug`,children:_.text}):null]})}):null,e.error?(0,U.jsx)(`p`,{className:`shrink-0 px-5 pb-2 text-center text-[0.8125rem] text-rose`,children:e.error}):null,(0,U.jsx)(`div`,{className:`flex shrink-0 items-center justify-center gap-3 px-4 pt-1 pb-4`,children:i?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(W,{label:x(e.muted?`video.unmute`:`video.mute`),on:!e.muted,onClick:e.toggleMute,children:e.muted?(0,U.jsx)(ie,{className:`size-5`}):(0,U.jsx)(l,{className:`size-5`})}),(0,U.jsx)(W,{label:x(e.camera?`talk.cameraOff`:`talk.camera`),on:e.camera,onClick:()=>e.camera?e.stopCamera():void e.startCamera(),children:e.camera?(0,U.jsx)(O,{className:`size-5`}):(0,U.jsx)(_e,{className:`size-5`})}),e.camera&&xe?(0,U.jsx)(W,{label:x(`video.flip`),onClick:()=>void e.flipCamera(),children:(0,U.jsx)(f,{className:`size-5`})}):null,(0,U.jsx)(W,{label:x(`video.leave`),danger:!0,onClick:p,children:(0,U.jsx)(ae,{className:`size-5`})})]}):(0,U.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[(0,U.jsxs)(`button`,{type:`button`,disabled:a||!t?.talk,onClick:()=>void d(),className:`flex h-12 items-center gap-2 rounded-full bg-emerald-500 px-6 font-medium text-[0.9375rem] text-white transition hover:brightness-110 disabled:opacity-50`,children:[a?(0,U.jsx)(h,{className:`size-4`}):n?(0,U.jsx)(O,{className:`size-5`}):(0,U.jsx)(l,{className:`size-5`}),x(c?`video.rejoin`:n?`video.join`:`talk.start`)]}),!c&&!e.error?(0,U.jsx)(`p`,{className:`max-w-sm text-center text-[0.75rem] text-white/50`,children:x(n?`video.hint`:`talk.joinHint`)}):null]})})]})}var Te=e=>L[e.kind]!==`device`,Ee=1024,De=4e3;function Oe(e,t){return e?e.length>t?`${e.slice(0,t)} …`:e:``}function ke(e,t,n=!1){let r=[`status: ${e.status}`,`camera: ${n?`on`:`off`}`];if(e.ask)return r.push(e.ask.kind===`confirm`?`question: the step wants to "${e.ask.action.summary}" in ${e.ask.service}; answer_ask allows or skips it`:`question: a sign-in at ${e.ask.site.host}; the person types it on the screen, wait`),r.join(`
|
|
2
|
-
`);if(e.status===`running`){let t=[...e.events].reverse().find(e=>e.type===`tool`||e.type===`info`||e.type===`step_started`);return r.push(`working on: ${e.step?.title??``}`),t&&r.push(`doing: ${b(t)}`),r.join(`
|
|
3
|
-
`)}if(e.status===`done`){r.push(`done. made:`);for(let{step:t,output:n}of e.shown)r.push(`- ${t.title}: ${Oe(n?.text,400)||`(a file, on the screen)`}`);return r.join(`
|
|
4
|
-
`)}if(e.status===`failed`)return r.push(`failed: ${e.error??``}; go_back or the person retries on the screen`),r.join(`
|
|
5
|
-
`);if(t){r.push(`page: ${t.step.title}`);for(let e of t.fields){let n=t.values[e.id],i=n!=null&&n!==``,a=Te(e)?`by voice`:e.kind===`image`?`with the camera (take_photo) or on the screen`:`on the screen only`,o=e.options?.length?`; options: ${e.options.join(` | `)}`:``;r.push(`- field ${e.id} (${e.kind}${e.required?`, required`:``}, ${a}): ${e.label}${e.help?` – ${e.help}`:``}${o}${i?` = ${Oe(String(Array.isArray(n)?n.join(`, `):n),120)}`:` = (open)`}`)}return r.join(`
|
|
6
|
-
`)}if(e.step?.type===`review`){r.push(`review: ${e.step.title}`);for(let{step:t,output:n}of e.shown)r.push(`- ${t.id} "${t.title}": ${Oe(n?.text,600)||`(a picture or file, on the screen)`}`);return r.push(`regenerate allowed: ${e.step.regenerate?`yes`:`no`}`),r.join(`
|
|
7
|
-
`)}return r.push(`step: ${e.step?.title??``}`),r.join(`
|
|
8
|
-
`)}function Ae(e,t,n,r){let[i,a]=(0,H.useState)(`off`),[o,s]=(0,H.useState)(null),[c,l]=(0,H.useState)(!1),[u,d]=(0,H.useState)(!1),[f,p]=(0,H.useState)(!1),[m,h]=(0,H.useState)(`environment`),[g,_]=(0,H.useState)(!1),[y,b]=(0,H.useState)([]),S=(0,H.useRef)(null),C=(0,H.useRef)(null),w=(0,H.useRef)(0),T=(0,H.useRef)(!1);T.current=f;let E=(0,H.useRef)(null),D=(0,H.useRef)(null),O=(0,H.useRef)(null),k=(0,H.useRef)(null),A=(0,H.useRef)(t);A.current=t;let j=(0,H.useRef)(r);j.current=r;let M=(0,H.useRef)(n);M.current=n;let N=(0,H.useRef)(``),P=(0,H.useCallback)(e=>{let t=D.current;t&&t.readyState===`open`&&t.send(JSON.stringify(e))},[]),F=(0,H.useCallback)(()=>{let e=S.current;if(!T.current||!e||e.videoWidth===0)return null;let t=Math.min(1,Ee/e.videoWidth),n=document.createElement(`canvas`);return n.width=Math.round(e.videoWidth*t),n.height=Math.round(e.videoHeight*t),n.getContext(`2d`)?.drawImage(e,0,0,n.width,n.height),n.toDataURL(`image/jpeg`,.75)},[]),I=(0,H.useCallback)(()=>{for(let e of C.current?.getTracks()??[])e.stop();C.current=null,S.current&&(S.current.srcObject=null),p(!1)},[]),L=(0,H.useCallback)(async e=>{if(C.current)return;let t=e??`environment`;try{let e=await navigator.mediaDevices.getUserMedia({video:{facingMode:{ideal:t},width:{ideal:1280}},audio:!1});C.current=e;let n=e.getVideoTracks()[0]?.getSettings().facingMode;h(n===`user`||n===`environment`?n:t),S.current&&(S.current.srcObject=e,await S.current.play().catch(()=>void 0)),p(!0)}catch(e){s(e.name===`NotAllowedError`?x(`talk.cameraDenied`):e.message)}},[]),R=(0,H.useCallback)(async()=>{let e=m===`user`?`environment`:`user`;I(),await L(e)},[m,I,L]),z=(0,H.useCallback)(()=>{_(e=>{for(let t of k.current?.getAudioTracks()??[])t.enabled=e;return!e})},[]),B=(0,H.useCallback)(()=>{I(),D.current?.close(),D.current=null,E.current?.close(),E.current=null;for(let e of k.current?.getTracks()??[])e.stop();k.current=null,O.current&&=(O.current.srcObject=null,O.current.remove(),null),N.current=``,l(!1),d(!1),_(!1),a(`off`)},[I]);(0,H.useEffect)(()=>()=>B(),[B]);let V=(0,H.useCallback)(async(t,n)=>{let r=A.current,i=j.current,a=M.current;switch(t){case`get_state`:return r?ke(r,i,T.current):`no run`;case`look`:{let e=F();return e?(P({type:`conversation.item.create`,item:{type:`message`,role:`user`,content:[{type:`input_text`,text:`[camera] what the person shows right now`},{type:`input_image`,image_url:e}]}}),`a picture arrived as the next message`):`the camera is off; ask the person to switch it on`}case`take_photo`:{if(!i)return`no page is open`;let t=i.fields.find(e=>e.id===String(n.field??``));if(t?.kind!==`image`)return`no such photo field on this page`;let r=F();if(!r)return`the camera is off; ask the person to switch it on`;try{let n=await(await fetch(r)).blob(),a=new File([n],`photo-${Date.now()}.jpg`,{type:`image/jpeg`}),o=await v.upload(`/api/runs/${e}/uploads`,a),s=i.values[t.id],c=t.multiple?[...Array.isArray(s)?s:s?[s]:[],o.id]:o.id,l=i.setField(t.id,c);return l?`refused: ${l}`:`the photo is in the field`}catch(e){return`failed: ${e.message}`}}case`set_field`:{if(!i)return`no page is open`;let e=i.setField(String(n.field??``),n.value);return e?`refused: ${e}`:`kept`}case`submit_page`:{if(!i)return`no page is open`;let e=i.fields.filter(e=>e.required&&Te(e)&&e.kind!==`toggle`&&(i.values[e.id]===void 0||i.values[e.id]===null||i.values[e.id]===``));return e.length?`still open: ${e.map(e=>e.id).join(`, `)}`:(i.submit(),`sent; wait for the next state`)}case`accept_review`:return r?.step?.type===`review`?await a.accept(r.step.id)?`accepted`:a.error??`refused`:`no review is open`;case`regenerate`:return r?.step?.type===`review`?await a.regenerate(r.step.id,String(n.target??``),String(n.note??``))?`the wizard makes it again; wait`:a.error??`refused`:`no review is open`;case`answer_ask`:if(!r?.ask)return`no question is open`;try{return await v.post(`/api/runs/${e}/ask/${r.ask.id}`,{type:n.allow?`done`:`skip`}),n.allow?`allowed`:`skipped`}catch(e){return`refused: ${e.message}`}case`go_back`:return await a.back()?`went back; wait for the state`:a.error??`refused`;default:return`unknown tool ${t}`}},[e,F,P]),ee=(0,H.useCallback)(async()=>{if(!E.current){s(null),b([]),a(`connecting`);try{let t=await v.post(`/api/runs/${e}/talk`),n=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}});k.current=n;let r=new RTCPeerConnection;E.current=r;let i=document.createElement(`audio`);i.autoplay=!0,i.setAttribute(`playsinline`,``),document.body.append(i),O.current=i,r.ontrack=e=>{i.srcObject=e.streams[0]};for(let e of n.getTracks())r.addTrack(e,n);let o=r.createDataChannel(`oai-events`);D.current=o,o.onmessage=e=>{let t;try{t=JSON.parse(e.data)}catch{return}switch(t.type){case`output_audio_buffer.started`:l(!0);break;case`output_audio_buffer.stopped`:case`output_audio_buffer.cleared`:l(!1);break;case`input_audio_buffer.speech_started`:{d(!0);let e=Date.now()-w.current>De?F():null;e&&(w.current=Date.now(),P({type:`conversation.item.create`,item:{type:`message`,role:`user`,content:[{type:`input_text`,text:`[camera] what the person shows while speaking`},{type:`input_image`,image_url:e}]}}));break}case`input_audio_buffer.speech_stopped`:d(!1);break;case`response.output_audio_transcript.done`:case`conversation.item.input_audio_transcription.completed`:{let e=String(t.transcript??``).trim();if(e){let n=t.type===`response.output_audio_transcript.done`?`bot`:`me`;b(t=>[...t.slice(-199),{id:`${Date.now()}:${n}`,who:n,text:e}])}break}case`response.function_call_arguments.done`:{let e=String(t.name??``),n=String(t.call_id??``),r={};try{r=JSON.parse(String(t.arguments??`{}`))}catch{}V(e,r).then(e=>{P({type:`conversation.item.create`,item:{type:`function_call_output`,call_id:n,output:e}}),P({type:`response.create`})});break}case`error`:s(String(t.error?.message??`error`))}},o.onopen=()=>{a(`live`);let e=A.current;e&&(N.current=ke(e,j.current,T.current),P({type:`conversation.item.create`,item:{type:`message`,role:`user`,content:[{type:`input_text`,text:`[state]\n${N.current}\n\nGreet the person in one sentence and ask the first open field.`}]}}),P({type:`response.create`}))},o.onclose=()=>{E.current===r&&B()};let c=await r.createOffer();await r.setLocalDescription(c);let u=await fetch(t.endpoint,{method:`POST`,headers:{authorization:`Bearer ${t.clientSecret}`,"content-type":`application/sdp`},body:c.sdp});if(!u.ok)throw Error(`${x(`talk.failed`)} (${u.status})`);await r.setRemoteDescription({type:`answer`,sdp:await u.text()})}catch(e){B(),s(e.name===`NotAllowedError`?x(`chat.micDenied`):e.message),a(`error`)}}},[e,V,F,P,B]);return(0,H.useEffect)(()=>{if(i!==`live`||!t)return;let e=ke(t,r,f);if(e===N.current)return;let n=N.current;N.current=e,P({type:`conversation.item.create`,item:{type:`message`,role:`user`,content:[{type:`input_text`,text:`[state]\n${e}`}]}}),(t.status===`running`&&n.startsWith(`status: running`)&&!n.includes(`working on: `)||t.status!==`running`||n.split(`
|
|
9
|
-
`)[1]!==e.split(`
|
|
10
|
-
`)[1])&&P({type:`response.create`})},[i,t,r,f,P]),{state:i,error:o,speaking:c,listening:u,start:ee,stop:B,camera:f,facing:m,startCamera:L,stopCamera:I,flipCamera:R,muted:g,toggleMute:z,captions:y,video:S}}var G=(e,t,n)=>({key:e,who:`bot`,node:t,...n}),K=(e,t,n)=>({key:e,who:`me`,node:t,...n}),je=(0,H.createContext)(null),q=(0,H.createContext)(null);function Me(){return(0,H.useContext)(q)?.voice??null}function Ne({children:e}){let t=(0,H.useContext)(je);return t?(0,be.createPortal)(e,t):null}function Pe({header:e,footer:t,children:n}){let[r,i]=(0,H.useState)(null),a=(0,H.useRef)(null),o=(0,H.useRef)(null),s=(0,H.useRef)(!0);return(0,H.useLayoutEffect)(()=>{let e=a.current,t=o.current;if(!e||!t)return;let n=e.scrollTop,r=()=>{e.scrollHeight-e.scrollTop-e.clientHeight<120?s.current=!0:e.scrollTop<n&&(s.current=!1),n=e.scrollTop},i=null,c=new ResizeObserver(()=>{let r=t.querySelector(`[data-anchor]`);r&&r!==i?(i=r,e.scrollTop+=r.getBoundingClientRect().top-e.getBoundingClientRect().top-12,s.current=!1,n=e.scrollTop):s.current&&(e.scrollTop=e.scrollHeight)});return e.scrollTop=e.scrollHeight,e.addEventListener(`scroll`,r,{passive:!0}),c.observe(t),c.observe(e),()=>{c.disconnect(),e.removeEventListener(`scroll`,r)}},[]),(0,U.jsx)(je.Provider,{value:r,children:(0,U.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[e,(0,U.jsx)(`div`,{ref:a,className:`min-h-0 flex-1 overflow-y-auto overscroll-contain`,children:(0,U.jsx)(`div`,{ref:o,className:`mx-auto flex w-full max-w-[760px] flex-col gap-3 px-3 pt-5 pb-4 sm:px-6`,children:n})}),(0,U.jsxs)(`div`,{className:`shrink-0 border-border-soft border-t bg-background`,onPointerDownCapture:()=>{s.current=!0},onKeyDownCapture:()=>{s.current=!0},children:[(0,U.jsx)(`div`,{ref:i,className:`mx-auto w-full max-w-[760px] px-3 pt-3 sm:px-6`}),t]})]})})}function J({avatar:e,lines:t}){let n=(0,H.useContext)(q),r=(0,H.useMemo)(()=>t.map(e=>({key:e.key,who:e.who,spoken:!e.bare&&!e.wide})),[t]),i=(0,H.useCallback)(e=>{let t=document.querySelector(`[data-say="${CSS.escape(e)}"]`);return t?.querySelector(`[data-say-text]`)?.getAttribute(`data-say-text`)??t?.innerText??null},[]);re(!!n?.readAloud,n?.lang??s,r,i);let a=[];for(let e of t){let t=a.at(-1);t&&t.who===`bot`&&e.who===`bot`?t.lines.push(e):a.push({who:e.who,lines:[e]})}return a.map((t,n)=>t.who===`bot`?(0,U.jsxs)(`div`,{className:`flex items-start gap-2.5`,children:[(0,U.jsx)(`div`,{className:`sticky top-1 shrink-0 pt-0.5`,children:(0,U.jsx)(le,{kind:e,size:30,interactive:n>=a.length-2})}),(0,U.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-col items-start gap-1.5`,children:t.lines.map(e=>(0,U.jsx)(`div`,{"data-anchor":e.anchor?``:void 0,"data-say":e.key,className:g(`animate-rise`,e.bare?`w-full pt-1`:`rounded-2xl rounded-tl-md text-[0.9375rem] text-ink leading-relaxed`,!e.bare&&(e.wide?g(`w-full bg-card p-4 shadow-soft ring-1 ring-border-soft`,e.wide===`most`&&`md:w-4/5`):`max-w-[min(36rem,100%)] bg-card px-4 py-2.5 shadow-soft ring-1 ring-border-soft`),e.tone===`error`&&`bg-rose-tint text-rose shadow-none ring-0`),children:e.node},e.key))})]},t.lines[0].key):t.lines.map(e=>(0,U.jsxs)(`div`,{className:`flex animate-rise flex-col items-end gap-1 pl-10`,children:[(0,U.jsx)(`div`,{className:`max-w-[min(32rem,100%)] whitespace-pre-wrap break-words rounded-2xl rounded-br-md bg-primary px-4 py-2.5 text-[0.9375rem] text-primary-foreground leading-relaxed`,children:e.node}),e.onEdit?(0,U.jsxs)(`button`,{type:`button`,onClick:e.onEdit,className:`inline-flex items-center gap-1 px-1 text-[0.75rem] text-ink-4 transition hover:text-ink-2 coarse:min-h-9`,children:[(0,U.jsx)(_,{className:`size-3`}),` `,x(`chat.change`)]}):null]},e.key)))}function Fe(){return(0,U.jsx)(`span`,{className:`inline-flex items-center gap-1 py-1.5`,role:`status`,"aria-label":x(`run.working`),children:[0,1,2].map(e=>(0,U.jsx)(`span`,{className:`size-1.5 animate-typing rounded-full bg-ink-3`,style:{animationDelay:`${e*160}ms`}},e))})}function Y({children:e}){return(0,U.jsx)(`div`,{className:`flex flex-wrap items-center gap-2`,children:e})}var X=(e,t)=>G(e,(0,U.jsx)(Y,{children:t}),{bare:!0});function Z({onClick:e,children:t,primary:n,on:r,disabled:i,busy:a}){return(0,U.jsxs)(`button`,{type:`button`,"aria-pressed":r,disabled:i||a,onClick:e,className:g(`inline-flex h-10 items-center gap-1.5 rounded-full px-4 font-medium text-[0.875rem] transition active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50 coarse:h-11`,n?`bg-primary text-primary-foreground hover:brightness-[1.06]`:r?`bg-ember-tint text-ink ring-1 ring-ember`:`bg-card text-ink-2 ring-1 ring-input hover:text-ink hover:ring-ink-4`),children:[a?(0,U.jsx)(h,{className:`size-4`}):null,t]})}function Ie({initial:e=``,placeholder:t,multiline:n,inputProps:r,busy:i,disabled:a,inputRef:o,onSend:s}){let[u,f]=(0,H.useState)(e),p=(0,H.useRef)(null),_=o??p,v=(0,H.useContext)(q),y=N(u,f,{endpoint:v?`/api/runs/${v.runId}/transcribe`:void 0}),b=!!v&&y.supported&&!a;(0,H.useEffect)(()=>{if(!b)return;let e=e=>{(e.metaKey||e.ctrlKey)&&e.shiftKey&&e.key.toLowerCase()===`m`&&(e.preventDefault(),y.toggle())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[b,y.toggle]),(0,H.useEffect)(()=>{!D&&!a&&_.current?.focus()},[a,_]);let S=()=>{i||a||(y.listening&&y.toggle(),s(u)!==!1&&f(``))},C=y.listening?x(`chat.listening`):y.processing?x(`chat.transcribing`):t,w=v?.voice??null,T=!!v?.call,E=v&&!T&&(ce||b||w)?(0,U.jsxs)(`div`,{className:`mb-1 flex shrink-0 items-center`,children:[w?(0,U.jsx)(d,{label:x(w.state===`live`?`talk.stop`:w.state===`connecting`?`talk.connecting`:`talk.start`),"aria-pressed":w.state===`live`,disabled:w.state===`connecting`,onClick:()=>w.state===`live`?w.stop():void w.start(),className:g(`size-9`,w.state===`live`&&`bg-rose-tint text-rose hover:bg-rose-tint hover:text-rose`,w.state===`off`&&v.talk&&`bg-primary text-primary-foreground hover:bg-primary`),children:w.state===`connecting`?(0,U.jsx)(h,{className:`size-4`}):w.state===`live`?(0,U.jsx)(ae,{className:`size-4`}):(0,U.jsx)(ne,{className:`size-4`})}):null,w?.state===`live`?(0,U.jsx)(d,{label:x(w.camera?`talk.cameraOff`:`talk.camera`),"aria-pressed":w.camera,onClick:()=>w.camera?w.stopCamera():void w.startCamera(),className:g(`size-9`,w.camera&&`text-ink`),children:w.camera?(0,U.jsx)(O,{className:`size-4`}):(0,U.jsx)(_e,{className:`size-4`})}):null,ce?(0,U.jsx)(d,{label:x(v.readAloud?`chat.readAloudOff`:`chat.readAloud`),"aria-pressed":v.readAloud,onClick:()=>v.setReadAloud(!v.readAloud),className:g(`size-9`,v.readAloud&&`text-ink`),children:v.readAloud?(0,U.jsx)(se,{className:`size-4`}):(0,U.jsx)(ye,{className:`size-4`})}):null,b?(0,U.jsx)(d,{label:x(y.listening?`chat.dictateStop`:`chat.dictate`),"aria-pressed":y.listening,disabled:y.processing,onClick:y.toggle,className:g(`size-9`,y.listening&&`bg-rose-tint text-rose hover:bg-rose-tint hover:text-rose`),children:y.processing?(0,U.jsx)(h,{className:`size-4`}):y.listening?(0,U.jsx)(m,{className:`size-3.5 animate-pulse-dot fill-current`}):(0,U.jsx)(l,{className:`size-4`})}):null]}):null;return(0,U.jsxs)(`form`,{className:`pb-3`,onSubmit:e=>{e.preventDefault(),S()},children:[w&&!T?(0,U.jsx)(`video`,{ref:w.video,muted:!0,playsInline:!0,autoPlay:!0,className:g(`mb-2 ml-auto w-32 rounded-xl bg-black object-cover shadow-soft ring-1 ring-border-soft`,w.camera?`block`:`hidden`)}):null,(0,U.jsxs)(`div`,{className:g(`flex items-end gap-1 rounded-[1.375rem] border border-input bg-card pr-1.5 pl-1 transition focus-within:border-focus focus-within:ring-4 focus-within:ring-focus-glow`,a&&`opacity-60`),children:[E,n?(0,U.jsx)(c,{ref:_,minRows:1,maxRows:6,value:u,disabled:a,placeholder:C,autoCapitalize:`sentences`,onChange:e=>f(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!D&&!e.nativeEvent.isComposing&&(e.preventDefault(),S())},className:`min-h-11 border-0 bg-transparent py-2.5 shadow-none focus:ring-0`}):(0,U.jsx)(`input`,{ref:_,...r,value:u,disabled:a,placeholder:C,enterKeyHint:`send`,onChange:e=>f(e.target.value),className:`h-11 min-w-0 flex-1 bg-transparent px-3 text-[0.9375rem] text-ink outline-none placeholder:text-ink-4`}),(0,U.jsx)(`button`,{type:`submit`,"aria-label":x(`chat.send`),title:x(`chat.send`),disabled:i||a,className:`mb-1 flex size-9 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground transition hover:brightness-[1.06] disabled:opacity-40`,children:i?(0,U.jsx)(h,{className:`size-4`}):(0,U.jsx)(k,{className:`size-4`})})]}),y.error?(0,U.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-rose`,children:y.error===`denied`?x(`chat.micDenied`):y.error}):T?null:w?.error?(0,U.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-rose`,children:w.error}):w?.state===`live`?(0,U.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-ink-3`,children:w.speaking?x(`talk.speaking`):w.listening?x(`talk.listening`):x(`talk.live`)}):v?.talk&&w?.state===`off`?(0,U.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-ink-3`,children:x(`talk.hint`)}):null]})}function Q({placeholder:e=x(`chat.above`)}){return(0,U.jsx)(Ne,{children:(0,U.jsx)(Ie,{disabled:!0,placeholder:e,onSend:()=>!1})})}function Le(e){let t=L[e.kind];return t===`typed`&&!e.scan?`typed`:t===`tapped`?`tapped`:`control`}var Re=e=>e==null||e===``||Array.isArray(e)&&e.length===0;function ze(e,t){let n=e.kind===`toggle`||e.kind===`connection`||e.kind===`list`;if(Re(t))return e.required&&!n?x(`chat.required`):null;let r=String(t).trim();if(e.kind===`email`&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r))return x(`chat.badEmail`);if(e.kind===`url`)try{new URL(r)}catch{return x(`chat.badUrl`)}return e.kind===`number`&&!Number.isFinite(Number(r.replace(`,`,`.`)))?x(`chat.badNumber`):Array.isArray(t)&&e.multiple&&e.min&&t.length<e.min?x(`run.filesMin`,{n:t.length,min:e.min}):null}function Be(e,t){let n=e.kind===`textarea`?t.replace(/\s+$/,``):t.trim();if(n)return e.kind===`url`&&!/^[a-z][a-z0-9+.-]*:/i.test(n)?`https://${n}`:n}function Ve({field:e}){return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`span`,{className:`font-medium`,children:e.label}),e.help?(0,U.jsx)(`span`,{className:`mt-0.5 block text-[0.8125rem] text-ink-3`,children:e.help}):null]})}function He({step:e,only:t}){return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`span`,{className:`font-medium`,children:e.title}),e.description?(0,U.jsx)(`span`,{className:`mt-0.5 block text-ink-2`,children:e.description}):null,t?.help?(0,U.jsx)(`span`,{className:`mt-1 block text-[0.8125rem] text-ink-3`,children:t.help}):null]})}function Ue({field:e,value:t,runId:n}){if(e.kind===`connection`)return(0,U.jsx)(U.Fragment,{children:typeof t==`string`&&t?t:x(`chat.connected`)});if(e.kind===`list`)return(0,U.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,U.jsx)(R,{className:`size-4`}),` `,x(`chat.checked`)]});if(e.kind===`toggle`)return(0,U.jsx)(U.Fragment,{children:x(t===!0?`run.yes`:`run.no`)});if(Re(t))return(0,U.jsx)(`span`,{className:`italic opacity-80`,children:x(`chat.skipped`)});switch(e.kind){case`multiselect`:return(0,U.jsx)(U.Fragment,{children:t.map(i).join(`, `)});case`select`:return(0,U.jsx)(U.Fragment,{children:i(String(t))});case`date`:{let e=new Date(`${String(t)}T00:00`);return(0,U.jsx)(U.Fragment,{children:Number.isNaN(e.getTime())?String(t):new Intl.DateTimeFormat(s,{dateStyle:`long`}).format(e)})}case`color`:return(0,U.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[(0,U.jsx)(`span`,{className:`size-4 rounded-full ring-1 ring-white/50`,style:{background:String(t)}}),String(t)]});case`image`:case`signature`:return(0,U.jsx)(`span`,{className:`-mx-1.5 flex flex-wrap gap-1.5`,children:(Array.isArray(t)?t:[String(t)]).map(t=>(0,U.jsx)(`img`,{src:r(`/api/runs/${n}/assets/${t}`),alt:``,className:g(`h-16 rounded-lg bg-white`,e.kind===`image`?`w-16 object-cover`:`object-contain px-1`)},t))});case`file`:{let e=Array.isArray(t)?t.length:1;return(0,U.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,U.jsx)(y,{className:`size-4`}),` `,x(e===1?`chat.file`:`chat.files`,{n:e})]})}case`audio`:{let e=t.seconds;return(0,U.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,U.jsx)(l,{className:`size-4`}),` `,x(`chat.voice`),e?` · ${Math.round(e)} s`:``]})}case`location`:{let e=t;return(0,U.jsx)(U.Fragment,{children:e.label||`${e.lat?.toFixed(5)}, ${e.lng?.toFixed(5)}`})}case`items`:return(0,U.jsx)(U.Fragment,{children:x(`chat.rows`,{n:Array.isArray(t)?t.length:0})});default:return(0,U.jsx)(U.Fragment,{children:String(t)})}}function We(e,t,n,r,i,a){let o=[G(t,(0,U.jsx)(He,{step:e,only:a}))];for(let e of i)a||o.push(G(`${t}:${e.id}`,(0,U.jsx)(Ve,{field:e}))),o.push(K(`${t}:${e.id}:a`,(0,U.jsx)(Ue,{field:e,value:n[e.id],runId:r})));return o}var Ge=(e,t)=>e.fields.filter(e=>!e.when&&!C(e)||t[e.id]!==void 0&&t[e.id]!==null);function Ke(e,t){let n=[];e.wizard.description&&n.push(G(`hello`,e.wizard.description)),e.wizard.intro&&n.push(G(`intro`,e.wizard.intro));for(let[t,r]of e.answered.entries()){let i=`${t}:${r.id}`;if(r.type===`page`){let t=r.fields.length===1?r.fields[0]:void 0;n.push(...We(r,i,e.values,e.id,Ge(r,e.values),t))}else r.type===`review`&&(n.push(G(i,(0,U.jsx)(`span`,{className:`font-medium`,children:r.title}))),n.push(K(`${i}:a`,x(`run.accept`))))}let r=n.at(-1);return t&&r?.who===`me`&&(n[n.length-1]={...r,onEdit:t}),n}function qe(e,t){return e.fields.filter(e=>!C(e)||t.decidedFields?.includes(e.id)).map(e=>t.options?.[e.id]?.length?{...e,options:t.options[e.id]}:e)}function Je({view:e,run:t,step:n,before:r}){let i=(0,H.useMemo)(()=>qe(n,e),[n,e]),a=e.known??{},[o,s]=(0,H.useState)(()=>B(n,e)),[c,l]=(0,H.useState)(()=>n.fields.some(t=>e.values[t.id]!==void 0)?p(qe(n,e),e.known??{},B(n,e)).slice(0,-1).map(e=>e.id):[]),[u,d]=(0,H.useState)({}),[f,m]=(0,H.useState)(!1),[h,g]=(0,H.useState)(!1),_=p(i,a,o),v=_.filter(e=>c.includes(e.id)),y=_.find(e=>!c.includes(e.id)),b=i.length===1?i[0]:void 0,S=v.at(-1),C=S?()=>l(e=>e.filter(e=>e!==S.id)):void 0;(0,H.useEffect)(()=>{let e=Object.keys(t.fieldErrors),n=p(i,a,o),r=n.findIndex(t=>e.includes(t.id));r>=0&&(l(n.slice(0,r).map(e=>e.id)),d(t.fieldErrors))},[t.fieldErrors]);let w=e=>{t.submitPage(n.id,e).then(g)},T=(0,H.useContext)(q),E=(0,H.useRef)(o);E.current=o;let D=T?.bindPage,O=(0,H.useRef)(w);O.current=w,(0,H.useEffect)(()=>{if(!D)return;let e=p(i,a,o);return D({step:n,fields:e,values:o,setField:(t,n)=>{let r=e.find(e=>e.id===t);return r?ze(r,n)||(s(e=>({...e,[t]:n})),l(e=>e.includes(t)?e:[...e,t]),d({}),null):`no such field on this page`},submit:()=>O.current(E.current)}),()=>D(null)},[D,n,i,a,o]);let k=e=>{if(!y)return!1;let t=ze(y,e);if(t)return d({[y.id]:t}),!1;let n={...o,[y.id]:e},r=[...c,y.id];return s(n),l(r),d({}),p(i,a,n).some(e=>!r.includes(e.id))||w(n),!0},j=[...r.map(e=>c.length?{...e,onEdit:void 0}:e),...We(n,`now:${n.id}`,o,e.id,v,b).map((e,t,n)=>t===n.length-1&&e.who===`me`&&y?{...e,onEdit:C}:e)];y?(Le(y)===`control`?j.push(G(`now:${n.id}:${y.id}:control`,(0,U.jsx)(A,{field:y,value:o[y.id],values:o,runId:e.id,view:e,closed:e.closed?.[y.id],onChange:e=>s(t=>({...t,[y.id]:e})),onBusy:m}),{wide:!0})):b||j.push(G(`now:${n.id}:${y.id}`,(0,U.jsx)(Ve,{field:y}))),u[y.id]&&j.push(G(`now:${n.id}:${y.id}:error`,u[y.id],{tone:`error`}))):t.busy||h?j.push(G(`sending`,(0,U.jsx)(Fe,{}))):t.error&&j.push(G(`send-error`,t.error,{tone:`error`}));let M=(0,U.jsx)(Q,{});if(h||!y&&c.length>0&&t.busy)M=(0,U.jsx)(Q,{placeholder:x(`run.working`)});else if(!y)j.push(X(`now:${n.id}:go`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(Z,{primary:!0,busy:t.busy,onClick:()=>w(o),children:n.cta||x(`run.next`)}),C?(0,U.jsx)(Z,{onClick:C,disabled:t.busy,children:x(`run.back`)}):null]})));else{let r=Le(y),i=!y.required&&y.kind!==`connection`&&y.kind!==`list`?(0,U.jsx)(Z,{onClick:()=>k(void 0),children:x(`chat.skip`)}):null;if(r===`typed`){i&&j.push(X(`now:${n.id}:${y.id}:replies`,i));let e=o[y.id];M=(0,U.jsx)(Ne,{children:(0,U.jsx)(Ie,{initial:Re(e)?``:String(e),multiline:y.kind===`textarea`,placeholder:y.placeholder||(b?y.label:x(`chat.placeholder`)),inputProps:Ye(y),busy:t.busy,onSend:e=>k(Be(y,e))},y.id)})}else if(r===`tapped`)j.push(G(`now:${n.id}:${y.id}:replies`,(0,U.jsx)(Xe,{field:y,view:e,value:o[y.id],onAnswer:k}),{bare:!0}));else{let e=_.filter(e=>!c.includes(e.id)).length===1;j.push(X(`now:${n.id}:${y.id}:replies`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(Z,{primary:!0,disabled:f,onClick:()=>k(o[y.id]),children:e&&n.cta?n.cta:x(`chat.send`)}),i]})))}}return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(J,{avatar:e.wizard.avatar,lines:j}),M]})}function Ye(e){switch(e.kind){case`number`:return{inputMode:`decimal`,autoComplete:`off`};case`email`:return{type:`email`,inputMode:`email`,autoComplete:`email`,autoCapitalize:`off`,autoCorrect:`off`,spellCheck:!1};case`url`:return{inputMode:`url`,autoComplete:`url`,autoCapitalize:`off`,autoCorrect:`off`,spellCheck:!1};case`date`:return{type:`date`};default:return V(e)}}function Xe({field:e,view:t,value:n,onAnswer:r}){let a=new Set(t.closed?.[e.id]?.values.map(String)),[o,s]=(0,H.useState)(Array.isArray(n)?n:[]);if(e.kind===`toggle`)return(0,U.jsxs)(Y,{children:[(0,U.jsx)(Z,{on:n===!1,disabled:a.has(`false`),onClick:()=>r(!1),children:x(`run.no`)}),(0,U.jsx)(Z,{on:n===!0,disabled:a.has(`true`),onClick:()=>r(!0),children:x(`run.yes`)})]});let c=e.options??[];return e.kind===`multiselect`?(0,U.jsxs)(Y,{children:[c.map(e=>(0,U.jsx)(Z,{on:o.includes(e),onClick:()=>s(t=>t.includes(e)?t.filter(t=>t!==e):c.filter(n=>n===e||t.includes(n))),children:i(e)},e)),(0,U.jsx)(Z,{primary:!0,disabled:e.required&&!o.length,onClick:()=>r(o),children:o.length||e.required?x(`chat.send`):x(`chat.skip`)})]}):(0,U.jsxs)(Y,{children:[c.map(e=>(0,U.jsx)(Z,{on:n===e,disabled:a.has(e),onClick:()=>r(e),children:i(e)},e)),e.required?null:(0,U.jsx)(Z,{onClick:()=>r(void 0),children:x(`chat.skip`)})]})}function Ze({view:e}){let t=(0,H.useMemo)(()=>[...e.events].reverse().find(t=>t.type===`step_started`&&t.stepId===e.step?.id),[e.events,e.step?.id]),n=t?new Date(t.at).getTime():Date.now(),[i,o]=(0,H.useState)(Date.now());(0,H.useEffect)(()=>{let e=setInterval(()=>o(Date.now()),1e3);return()=>clearInterval(e)},[]);let s=e.events.filter(e=>(e.type===`tool`||e.type===`info`)&&new Date(e.at).getTime()>=n-500),c=s.at(-1),l=[...s].reverse().find($e),u=[...new Set(s.map(e=>e.asset).filter(e=>!!e))];return(0,U.jsxs)(`div`,{className:g(`flex max-w-full flex-col gap-1`,l?`w-full`:`w-96`),"data-say-text":t?.message??e.step?.title??x(`run.working`),children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,U.jsx)(Fe,{}),(0,U.jsx)(`span`,{className:`font-medium`,children:t?.message??e.step?.title??x(`run.working`)}),(0,U.jsx)(`span`,{className:`text-[0.75rem] text-ink-4 tabular-nums`,children:x(`run.elapsed`,{s:Math.max(0,Math.round((i-n)/1e3))})})]}),c&&c!==l?(0,U.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-ink-3`,children:[(0,U.jsx)(a,{className:`size-3.5 shrink-0 animate-breathe text-ember`}),(0,U.jsx)(`span`,{className:`truncate`,children:b(c)})]}):null,l&&e.status===`running`?(0,U.jsx)(tt,{runId:e.id,event:l}):null,u.length?(0,U.jsx)(`div`,{className:`mt-1.5 flex flex-wrap gap-1.5`,children:u.slice(-6).map(t=>(0,U.jsx)(`img`,{src:r(`/api/runs/${e.id}/assets/${t}`),alt:``,className:`size-14 rounded-lg bg-paper-2 object-cover ring-1 ring-border-soft`},t))}):null]})}var Qe=new Set([`opens`,`clicks`,`clicksOn`,`types`,`typesText`,`selects`,`scrolls`,`presses`,`goesBack`,`waitsForPage`,`fastLoop`,`looksAtPage`,`personDrives`,`agentDrives`]);function $e(e){return!!e.note&&Qe.has(e.note.code)}var et=1e4;function tt({runId:e,event:t}){let[n,r]=(0,H.useState)(null),[i,a]=(0,H.useState)(`agent`),[o,s]=(0,H.useState)(!1),c=t.note?.code;if((0,H.useEffect)(()=>{c===`personDrives`?a(`person`):c===`agentDrives`&&a(`agent`)},[c]),(0,H.useEffect)(()=>{let t=()=>v.get(`/api/runs/${e}/browser/seat`).then(e=>a(e.seat)).catch(()=>void 0);if(t(),i!==`person`)return;let n=setInterval(t,et);return()=>clearInterval(n)},[e,i]),n!==null&&n>=t.id)return null;let l=i===`person`,u=async()=>{s(!0);try{let t=await v.post(`/api/runs/${e}/browser/seat`,{to:l?`agent`:`person`});a(t.seat)}catch{}finally{s(!1)}};return(0,U.jsx)(ee,{runId:e,driving:l,caption:b(t),hint:x(`browser.driving`),onBroken:()=>r(t.id),className:`mt-1.5`,action:(0,U.jsxs)(`button`,{type:`button`,disabled:o,onClick:()=>void u(),className:g(`flex h-8 items-center gap-1.5 rounded-full px-3 font-medium text-[0.8125rem] shadow-soft transition-colors disabled:opacity-60`,l?`bg-primary text-primary-foreground hover:bg-primary/90`:`bg-card/90 text-ink ring-1 ring-border-soft backdrop-blur hover:bg-card`),children:[l?(0,U.jsx)(he,{className:`size-3.5`}):(0,U.jsx)(pe,{className:`size-3.5`}),x(l?`browser.handBack`:`browser.takeOver`)]})},n??0)}function $({children:e,end:t}){return(0,U.jsxs)(`div`,{className:`mb-3 flex flex-wrap items-center justify-between gap-2`,children:[(0,U.jsx)(`h3`,{className:`font-display font-semibold text-[1rem]`,children:e}),t]})}function nt({view:e,run:t,step:n,before:r,asked:i,onNote:a}){let o=e.shown.filter(e=>e.output),[s,c]=(0,H.useState)(o.length===1?o[0].step.id:null),l=(0,H.useRef)(null),u=[...r,...i.map((e,t)=>K(`review:${n.id}:asked:${t}`,e)),G(`review:${n.id}`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`span`,{className:`font-medium`,children:n.title}),n.description?(0,U.jsx)(`span`,{className:`mt-0.5 block text-ink-2`,children:n.description}):null]}),{anchor:!0}),...o.map(({step:t,output:r})=>G(`review:${n.id}:${t.id}`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)($,{children:t.title}),(0,U.jsx)(z,{base:`/api/runs/${e.id}`,step:t,output:r,onSurfaceAction:n.regenerate?()=>{c(t.id),l.current?.focus()}:void 0})]}),{wide:!0})),...e.lists.map(t=>G(`review:${n.id}:list:${t.def.id}`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)($,{children:t.def.title}),t.def.check?(0,U.jsx)(w,{runId:e.id,list:t}):(0,U.jsx)(F,{runId:e.id,list:t,editable:!0})]}),{wide:!0}))];t.error&&u.push(G(`review-error`,t.error,{tone:`error`}));let d=n.regenerate&&o.length>0;return u.push(X(`review:${n.id}:replies`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsxs)(Z,{primary:!0,busy:t.busy,onClick:()=>void t.accept(n.id),children:[(0,U.jsx)(R,{className:`size-4`}),` `,x(`run.accept`)]}),d&&o.length>1?o.map(({step:e})=>(0,U.jsx)(Z,{on:s===e.id,onClick:()=>c(e.id),children:e.title},e.id)):null]}))),(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(J,{avatar:e.wizard.avatar,lines:u}),d?(0,U.jsx)(Ne,{children:(0,U.jsx)(Ie,{multiline:!0,inputRef:l,busy:t.busy,placeholder:o.length>1&&!s?x(`run.feedbackPick`):x(`run.feedbackPlaceholder`),disabled:!s,onSend:e=>{let r=e.trim();return!r||!s?!1:(a(r),t.regenerate(n.id,s,r),!0)}})}):(0,U.jsx)(Q,{})]})}function rt({view:e,run:t,step:n,before:r,onRestart:i}){let a=e.shown.filter(e=>e.output),o=`/api/runs/${e.id}`,s=[...r,G(`result:${n.id}`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`span`,{className:`font-display font-semibold text-[1.0625rem]`,children:n.title}),n.message?(0,U.jsx)(`span`,{className:`mt-0.5 block text-ink-2`,children:n.message}):null]}),{anchor:!0}),...a.map(({step:e,output:t,formats:n,label:r})=>G(`result:${e.id}`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)($,{end:(0,U.jsx)(I,{base:o,stepId:e.id,formats:n,title:r??e.title}),children:r??e.title}),(0,U.jsx)(z,{base:o,step:e,output:t}),t?.assets?.some(e=>e.ai)?(0,U.jsx)(`p`,{className:`mt-3 text-[0.75rem] text-ink-3 leading-relaxed`,children:x(`ai.publish`)}):null]}),{wide:!0})),...e.lists.map(t=>G(`result:list:${t.def.id}`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)($,{end:(0,U.jsx)(T,{runId:e.id,list:t}),children:t.label??t.def.title}),(0,U.jsx)(F,{runId:e.id,list:t,editable:!0})]}),{wide:!0}))];return s.push(X(`result:replies`,(0,U.jsxs)(U.Fragment,{children:[a.length?(0,U.jsx)(ue,{runId:e.id,title:`${n.title} · ${e.wizard.title}`,initial:e.shareUrl?{url:e.shareUrl,expiresAt:e.expiresAt}:null}):null,i?(0,U.jsxs)(Z,{onClick:i,children:[(0,U.jsx)(u,{className:`size-4`}),` `,x(`run.again`)]}):null,e.canBack?(0,U.jsx)(Z,{onClick:()=>void t.back(),disabled:t.busy,children:x(`run.back`)}):null,e.keeps?(0,U.jsx)(`span`,{className:`ml-1`,children:(0,U.jsx)(j,{runId:e.id})}):null]}))),(0,U.jsx)(J,{avatar:e.wizard.avatar,lines:s})}function it({runId:e,onRestart:t,onView:n,header:r,footer:i,talk:a=!1,call:c=!1}){let l=de(e),{view:d}=l,[f,p]=(0,H.useState)(null),m=Ae(e,d,l,f);(0,H.useEffect)(()=>{n?.(d)},[d,n]);let[g,_]=oe(),v=(0,H.useMemo)(()=>({runId:e,lang:d?.lang??s,readAloud:g,setReadAloud:_,voice:d?.talk?m:null,talk:a,call:!!c,bindPage:p}),[e,d?.lang,d?.talk,g,_,m,a,c]);E(d?.status===`running`&&!d.ask),M(d);let[y,b]=(0,H.useState)({}),[C,w]=(0,H.useState)(null);(0,H.useEffect)(()=>{d&&d.status!==`running`&&w(null)},[d]);let T;if(l.notFound)T=(0,U.jsx)(`div`,{className:`py-24 text-center text-ink-3`,children:x(`run.notFound`)});else if(!d)T=(0,U.jsx)(`div`,{className:`flex justify-center py-24 text-ink-4`,children:(0,U.jsx)(h,{})});else{let e=d.step,n=d.status===`waiting_input`,r=Ke(d,d.canBack&&n&&!l.busy?()=>void l.back():void 0);if(d.status===`running`&&d.ask)T=(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(J,{avatar:d.wizard.avatar,lines:[...r,G(`ask:${d.ask.id}`,(0,U.jsx)(S,{runId:d.id,ask:d.ask}),{wide:!0})]}),(0,U.jsx)(Q,{})]});else if(d.status===`running`)T=(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(J,{avatar:d.wizard.avatar,lines:[...r,...C?[K(`note`,C)]:[],G(`working:${e?.id}`,(0,U.jsx)(Ze,{view:d}),{wide:d.events.some(t=>t.stepId===e?.id&&$e(t))?`most`:void 0})]}),(0,U.jsx)(Q,{placeholder:x(`run.working`)})]});else if(d.status===`failed`)T=(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(J,{avatar:d.wizard.avatar,lines:[...r,G(`failed`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(`span`,{className:`font-medium`,children:x(`run.failed`)}),d.error?(0,U.jsx)(`span`,{className:`mt-0.5 block`,children:(0,U.jsx)(o,{text:d.error})}):null]}),{tone:`error`}),X(`failed:replies`,(0,U.jsxs)(U.Fragment,{children:[(0,U.jsxs)(Z,{primary:!0,busy:l.busy,onClick:()=>void l.retry(),children:[(0,U.jsx)(u,{className:`size-4`}),` `,x(`run.retry`)]}),d.canBack?(0,U.jsx)(Z,{onClick:()=>void l.back(),disabled:l.busy,children:x(`run.back`)}):null]}))]}),(0,U.jsx)(Q,{})]});else if(d.status===`cancelled`)T=(0,U.jsx)(J,{avatar:d.wizard.avatar,lines:[...r,G(`cancelled`,x(`run.cancelled`)),...t?[X(`cancelled:replies`,(0,U.jsxs)(Z,{primary:!0,onClick:t,children:[(0,U.jsx)(u,{className:`size-4`}),` `,x(`run.again`)]}))]:[]]});else if(e?.type===`page`)T=(0,U.jsx)(Je,{view:d,run:l,step:e,before:r},e.id);else if(e?.type===`review`){let t=d.shown.map(e=>e.output?.at??``).join(`|`);T=(0,U.jsx)(nt,{view:d,run:l,step:e,before:r,asked:y[e.id]??[],onNote:t=>{w(t),b(n=>({...n,[e.id]:[...n[e.id]??[],t]}))}},`${e.id}:${t}`)}else T=e?.type===`result`?(0,U.jsx)(rt,{view:d,run:l,step:e,before:r,onRestart:t}):(0,U.jsx)(J,{avatar:d.wizard.avatar,lines:r})}return c?(0,U.jsx)(q.Provider,{value:v,children:(0,U.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col lg:flex-row`,children:[(0,U.jsx)(we,{voice:m,view:d,video:c===`video`,className:`h-[46dvh] shrink-0 lg:h-auto lg:min-h-0 lg:flex-1`}),(0,U.jsx)(`aside`,{className:`flex min-h-0 flex-1 flex-col border-border-soft border-t lg:w-[420px] lg:flex-none lg:border-t-0 lg:border-l`,children:(0,U.jsx)(Pe,{footer:i,children:T})})]})}):(0,U.jsx)(q.Provider,{value:v,children:(0,U.jsx)(Pe,{header:r,footer:i,children:T})})}export{J as a,Z as i,Pe as n,X as o,Q as r,Me as s,it as t};
|