@engenty/wizards-runtime 0.7.11 → 0.8.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/README.md +5 -1
- package/apps/runtime/dist/authoring/guide.js +14 -2
- package/apps/runtime/dist/cli/exec.js +4 -1
- package/apps/runtime/dist/connectors/builtin.js +4 -2
- package/apps/runtime/dist/connectors/index.js +35 -4
- package/apps/runtime/dist/connectors/smtp.js +221 -0
- package/apps/runtime/dist/db/migrations/tenant/0018_share_job.sql +18 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0018_snapshot.json +3460 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +7 -0
- package/apps/runtime/dist/db/schema.js +19 -0
- package/apps/runtime/dist/docs/dev/index.md +25 -13
- package/apps/runtime/dist/docs/dev/meta.json +8 -2
- package/apps/runtime/dist/docs/dev/wizard-format/agent-steps.md +112 -0
- package/apps/runtime/dist/docs/dev/wizard-format/branches.md +63 -0
- package/apps/runtime/dist/docs/dev/wizard-format/film-steps.md +47 -0
- package/apps/runtime/dist/docs/dev/wizard-format/generate-steps.md +57 -0
- package/apps/runtime/dist/docs/dev/wizard-format/index.md +188 -0
- package/apps/runtime/dist/docs/dev/wizard-format/lists-and-connections.md +65 -0
- package/apps/runtime/dist/docs/dev/wizard-format/meta.json +19 -0
- package/apps/runtime/dist/docs/dev/wizard-format/pages-and-fields.md +102 -0
- package/apps/runtime/dist/docs/dev/wizard-format/review-and-result.md +64 -0
- package/apps/runtime/dist/docs/dev/wizard-format/templates.md +57 -0
- package/apps/runtime/dist/docs/dev/wizard-format/validate.md +63 -0
- package/apps/runtime/dist/docs/dev/wizard-format/views-and-widgets.md +103 -0
- package/apps/runtime/dist/docs/dev/wizard-format/wizard-file.md +147 -0
- package/apps/runtime/dist/docs/user/run.md +21 -4
- package/apps/runtime/dist/docs/user/steps.md +26 -1
- package/apps/runtime/dist/docs/user/test-and-share.md +3 -2
- package/apps/runtime/dist/engine/requirements.js +22 -7
- package/apps/runtime/dist/engine/runner.js +17 -8
- package/apps/runtime/dist/env.js +5 -0
- package/apps/runtime/dist/harness/antigravity.js +2 -10
- package/apps/runtime/dist/harness/claude.js +2 -10
- package/apps/runtime/dist/harness/codex.js +5 -11
- package/apps/runtime/dist/harness/cursor.js +2 -10
- package/apps/runtime/dist/harness/env.js +23 -0
- package/apps/runtime/dist/harness/index.js +6 -3
- package/apps/runtime/dist/routes/runs.js +106 -6
- package/apps/runtime/dist/routes/studio.js +12 -0
- package/apps/runtime/dist/sharing/agent.js +65 -0
- package/apps/runtime/dist/sharing/files.js +121 -0
- package/apps/runtime/dist/sharing/index.js +298 -0
- package/apps/runtime/dist/sharing/jobs.js +186 -0
- package/apps/runtime/dist/sharing/state.js +116 -0
- package/apps/runtime/dist/sharing/targets/browser.js +131 -0
- package/apps/runtime/dist/sharing/targets/connector.js +63 -0
- package/apps/runtime/dist/sharing/targets/email.js +98 -0
- package/apps/runtime/dist/sharing/targets/slack.js +54 -0
- package/apps/runtime/dist/sharing/targets/storage.js +164 -0
- package/apps/runtime/dist/sharing/types.js +13 -0
- package/apps/runtime/dist/texts.js +108 -0
- package/apps/runtime/dist/tools/browser.js +48 -0
- package/apps/runtime/dist/tools/connector.js +3 -2
- package/apps/runtime/dist/tools/store.js +18 -1
- package/apps/web/dist/assets/AboutDialog-CiiSwL4t.js +1 -0
- package/apps/web/dist/assets/{ChangelogDialog-CZrd-MgC.js → ChangelogDialog-BEyz7LNE.js} +1 -1
- package/apps/web/dist/assets/ChatView-9RkWts5F.js +10 -0
- package/apps/web/dist/assets/EditorPage-CCsKKcYo.js +4 -0
- package/apps/web/dist/assets/{FlowPreview-oX_Emm7u.js → FlowPreview-CLf8WHiG.js} +1 -1
- package/apps/web/dist/assets/{Harness-DiB8CBdY.js → Harness-jc3jpWvI.js} +2 -2
- package/apps/web/dist/assets/NewWizardChannels-BPGZ4pfP.js +1 -0
- package/apps/web/dist/assets/NewWizardPage-tidycL7Y.js +7 -0
- package/apps/web/dist/assets/OnboardingPage-DtVuaIuv.js +1 -0
- package/apps/web/dist/assets/ProjectPage-BsWgCP5z.js +1 -0
- package/apps/web/dist/assets/PublicRunner-CkA_etKX.js +1 -0
- package/apps/web/dist/assets/{ReadOnly-CD5YWvrW.js → ReadOnly-BVwbqvpi.js} +1 -1
- package/apps/web/dist/assets/RunDrawer-CkFpnWCC.js +4 -0
- package/apps/web/dist/assets/{RunnerView-BW1h4x63.js → RunnerView-CxTFM-lx.js} +1 -1
- package/apps/web/dist/assets/SettingsPage-DM1wNAE7.js +1 -0
- package/apps/web/dist/assets/SetupPage-BKnQqiab.js +1 -0
- package/apps/web/dist/assets/{SharePage-B6u9kS12.js → SharePage-CTTSudtp.js} +1 -1
- package/apps/web/dist/assets/changelog-DBEwyB1f.js +1 -0
- package/apps/web/dist/assets/{esm-C-ZWeuhU.js → esm-DtNAg8uF.js} +1 -1
- package/apps/web/dist/assets/index-V1M59Yez.css +1 -0
- package/apps/web/dist/assets/index-xIz8znhq.js +14 -0
- package/apps/web/dist/assets/{oss-credits-Bc05Qv5H.js → oss-credits-BWE03Xax.js} +1 -1
- package/apps/web/dist/assets/{phone-BjmhIKuT.js → phone-5SYD9OrJ.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-Dpkp3f56.js → settings-menu-Bn5-7Lqk.js} +1 -1
- package/apps/web/dist/assets/ui-s39eGOtW.js +137 -0
- package/apps/web/dist/assets/{upload-JX9BcMTq.js → upload-Bevcvx5V.js} +1 -1
- package/apps/web/dist/assets/{wrench-BSxnPs2_.js → wrench-ZD5SCsz9.js} +1 -1
- package/apps/web/dist/index.html +3 -3
- package/apps/web/dist/mcp/flow.html +53 -53
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +22 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.js +26 -0
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +6 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +2 -0
- package/node_modules/@engenty-wizards/shared/dist/sharing.d.ts +135 -0
- package/node_modules/@engenty-wizards/shared/dist/sharing.js +11 -0
- package/node_modules/@engenty-wizards/shared/dist/store.d.ts +8 -0
- package/package.json +2 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/apps/runtime/dist/docs/dev/wizard-format.md +0 -125
- package/apps/web/dist/assets/AboutDialog-CPRAlD2H.js +0 -1
- package/apps/web/dist/assets/ChatView-DVeERQdi.js +0 -10
- package/apps/web/dist/assets/EditorPage-DhUoKcss.js +0 -4
- package/apps/web/dist/assets/NewWizardChannels-Ba3XGpro.js +0 -1
- package/apps/web/dist/assets/NewWizardPage-C2Oh2sMM.js +0 -7
- package/apps/web/dist/assets/OnboardingPage-D_4ShWrL.js +0 -1
- package/apps/web/dist/assets/ProjectPage-C58rq50b.js +0 -1
- package/apps/web/dist/assets/PublicRunner-CE0ohzyd.js +0 -1
- package/apps/web/dist/assets/RunDrawer-Cd8-qHV7.js +0 -4
- package/apps/web/dist/assets/SettingsPage-ChYLv-MG.js +0 -1
- package/apps/web/dist/assets/SetupPage-hX7deF0g.js +0 -1
- package/apps/web/dist/assets/changelog-Dn9LT4MS.js +0 -1
- package/apps/web/dist/assets/index-4jH2mkp7.js +0 -14
- package/apps/web/dist/assets/index-BwW652E-.css +0 -1
- package/apps/web/dist/assets/ui-DMmT-cSO.js +0 -137
|
@@ -1044,6 +1044,13 @@ export declare const deliverableSchema: z.ZodObject<{
|
|
|
1044
1044
|
zip: "zip";
|
|
1045
1045
|
}>>;
|
|
1046
1046
|
}, z.core.$strip>;
|
|
1047
|
+
/** One share target the result offers, with what its form starts with. */
|
|
1048
|
+
export declare const shareOptionSchema: z.ZodObject<{
|
|
1049
|
+
target: z.ZodString;
|
|
1050
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1051
|
+
values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1052
|
+
}, z.core.$strip>;
|
|
1053
|
+
export type ShareOption = z.infer<typeof shareOptionSchema>;
|
|
1047
1054
|
export declare const resultStepSchema: z.ZodObject<{
|
|
1048
1055
|
id: z.ZodString;
|
|
1049
1056
|
title: z.ZodString;
|
|
@@ -1100,6 +1107,11 @@ export declare const resultStepSchema: z.ZodObject<{
|
|
|
1100
1107
|
zip: "zip";
|
|
1101
1108
|
}>>;
|
|
1102
1109
|
}, z.core.$strip>>;
|
|
1110
|
+
share: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1111
|
+
target: z.ZodString;
|
|
1112
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1113
|
+
values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1114
|
+
}, z.core.$strip>>>;
|
|
1103
1115
|
}, z.core.$strip>;
|
|
1104
1116
|
export declare const stepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1105
1117
|
id: z.ZodString;
|
|
@@ -1764,6 +1776,11 @@ export declare const stepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1764
1776
|
zip: "zip";
|
|
1765
1777
|
}>>;
|
|
1766
1778
|
}, z.core.$strip>>;
|
|
1779
|
+
share: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1780
|
+
target: z.ZodString;
|
|
1781
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1782
|
+
values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1783
|
+
}, z.core.$strip>>>;
|
|
1767
1784
|
}, z.core.$strip>], "type">;
|
|
1768
1785
|
export type Step = z.infer<typeof stepSchema>;
|
|
1769
1786
|
export type PageStep = z.infer<typeof pageStepSchema>;
|
|
@@ -2765,6 +2782,11 @@ export declare const wizardSchema: z.ZodObject<{
|
|
|
2765
2782
|
zip: "zip";
|
|
2766
2783
|
}>>;
|
|
2767
2784
|
}, z.core.$strip>>;
|
|
2785
|
+
share: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2786
|
+
target: z.ZodString;
|
|
2787
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2788
|
+
values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2789
|
+
}, z.core.$strip>>>;
|
|
2768
2790
|
}, z.core.$strip>], "type">>;
|
|
2769
2791
|
}, z.core.$strip>;
|
|
2770
2792
|
export type WizardDefinition = z.infer<typeof wizardSchema>;
|
|
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import { tableColumnsSchema } from "./engenty/data-tables/index.js";
|
|
4
4
|
import { readNumber } from "./numbers.js";
|
|
5
5
|
import { outputShapeSchema, shapeOfFields } from "./shape.js";
|
|
6
|
+
import { isShareTargetId } from "./sharing.js";
|
|
6
7
|
import { CONNECTION_KINDS } from "./store.js";
|
|
7
8
|
import { surfaceComponentsSchema, validateSurface } from "./surface.js";
|
|
8
9
|
/** The engenty avatars a wizard can wear. Same cast as engenty's ui-core. */
|
|
@@ -731,11 +732,25 @@ export const deliverableSchema = z.object({
|
|
|
731
732
|
label: z.string().optional(),
|
|
732
733
|
formats: z.array(z.enum(FORMATS)).min(1),
|
|
733
734
|
});
|
|
735
|
+
/** One share target the result offers, with what its form starts with. */
|
|
736
|
+
export const shareOptionSchema = z.object({
|
|
737
|
+
/** "email", "slack", "browser", "storage:<connector>" or "connector:<connector>". */
|
|
738
|
+
target: z.string().min(1),
|
|
739
|
+
/** How the result names it, e.g. "Auf LinkedIn posten". Default: the target's own name. */
|
|
740
|
+
label: z.string().optional(),
|
|
741
|
+
/** Prefills the target's form by field id. Templates: {{field}}, {{steps.id}}, {{brand.name}}. */
|
|
742
|
+
values: z.record(z.string(), z.string()).optional(),
|
|
743
|
+
});
|
|
734
744
|
export const resultStepSchema = z.object({
|
|
735
745
|
...stepBase,
|
|
736
746
|
type: z.literal("result"),
|
|
737
747
|
message: z.string().optional(),
|
|
738
748
|
deliverables: z.array(deliverableSchema),
|
|
749
|
+
/**
|
|
750
|
+
* Where the person can send or publish the result besides the link and the downloads. Left
|
|
751
|
+
* out: the targets that need no model. An empty list: none.
|
|
752
|
+
*/
|
|
753
|
+
share: z.array(shareOptionSchema).max(12).optional(),
|
|
739
754
|
});
|
|
740
755
|
export const stepSchema = z.discriminatedUnion("type", [
|
|
741
756
|
pageStepSchema,
|
|
@@ -1487,6 +1502,17 @@ export function validateWizard(def, files) {
|
|
|
1487
1502
|
issues.push({ stepId: step.id, message: notShown(list) });
|
|
1488
1503
|
}
|
|
1489
1504
|
}
|
|
1505
|
+
for (const option of step.share ?? []) {
|
|
1506
|
+
if (!isShareTargetId(option.target)) {
|
|
1507
|
+
issues.push({
|
|
1508
|
+
stepId: step.id,
|
|
1509
|
+
message: `Unknown share target "${option.target}": use email, slack, browser, storage:<connector> or connector:<connector>.`,
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1512
|
+
for (const value of Object.values(option.values ?? {})) {
|
|
1513
|
+
checkTemplate(step, value);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1490
1516
|
break;
|
|
1491
1517
|
}
|
|
1492
1518
|
if ((step.next ?? []).filter(isOtherwise).length > 1) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type CardOption, type Format, type Lang, type ModelClass, type Step, type WizardDefinition } from "./definition.js";
|
|
2
|
+
import type { ShareJobView } from "./sharing.js";
|
|
2
3
|
import type { ConnectionView, ListDef, ListRow } from "./store.js";
|
|
3
4
|
import type { Surface } from "./surface.js";
|
|
4
5
|
import { type Gap, type Texts, type TextTable } from "./texts.js";
|
|
@@ -120,6 +121,8 @@ export interface ConfirmAsk extends AskBase {
|
|
|
120
121
|
};
|
|
121
122
|
/** What would be sent, as readable JSON. */
|
|
122
123
|
input: string;
|
|
124
|
+
/** Asked for this one thing: there is nothing to allow for the rest of the run. */
|
|
125
|
+
once?: boolean;
|
|
123
126
|
}
|
|
124
127
|
/** What a running step asks the person; the step waits for the answer. */
|
|
125
128
|
export type RunAsk = LoginAsk | ConfirmAsk;
|
|
@@ -212,6 +215,7 @@ declare const NOTES_EN: {
|
|
|
212
215
|
readonly looksAtPage: "Looking at the page";
|
|
213
216
|
readonly waitsForSignIn: "Waiting for you to sign in to {name}";
|
|
214
217
|
readonly downloads: "Downloading {name}";
|
|
218
|
+
readonly attaches: "Attaching {name}";
|
|
215
219
|
readonly runs: "Running: {command}";
|
|
216
220
|
readonly python: "Running Python";
|
|
217
221
|
readonly runsProgram: "Working through the data in one go";
|
|
@@ -565,6 +569,8 @@ export interface RunView {
|
|
|
565
569
|
shareUrl: string | null;
|
|
566
570
|
/** When the run and its shared link are deleted; null = kept. */
|
|
567
571
|
expiresAt: string | null;
|
|
572
|
+
/** The result on its way to a share target, or the last one that arrived or failed. */
|
|
573
|
+
shareJob: ShareJobView | null;
|
|
568
574
|
}
|
|
569
575
|
/** How a run in the viewer's language shows. */
|
|
570
576
|
export interface RunTranslation {
|
|
@@ -48,6 +48,7 @@ const NOTES_EN = {
|
|
|
48
48
|
looksAtPage: "Looking at the page",
|
|
49
49
|
waitsForSignIn: "Waiting for you to sign in to {name}",
|
|
50
50
|
downloads: "Downloading {name}",
|
|
51
|
+
attaches: "Attaching {name}",
|
|
51
52
|
runs: "Running: {command}",
|
|
52
53
|
python: "Running Python",
|
|
53
54
|
runsProgram: "Working through the data in one go",
|
|
@@ -341,6 +342,7 @@ const NOTES_DE = {
|
|
|
341
342
|
looksAtPage: "Sieht sich die Seite an",
|
|
342
343
|
waitsForSignIn: "Wartet auf deine Anmeldung bei {name}",
|
|
343
344
|
downloads: "Lädt {name} herunter",
|
|
345
|
+
attaches: "Hängt {name} an",
|
|
344
346
|
runs: "Führt aus: {command}",
|
|
345
347
|
runsProgram: "Arbeitet die Daten in einem Zug durch",
|
|
346
348
|
python: "Führt Python aus",
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { Format, Lang } from "./definition.js";
|
|
2
|
+
import type { RunAsk } from "./run.js";
|
|
3
|
+
import type { ConnectionView } from "./store.js";
|
|
4
|
+
/**
|
|
5
|
+
* Sharing a finished result beyond the link and the downloads: a share target sends or publishes
|
|
6
|
+
* it — by e-mail, into a cloud folder, to a Slack channel, through a connector, on a website.
|
|
7
|
+
*/
|
|
8
|
+
/** The targets every runtime has. A connector adds `storage:<connector>` or `connector:<connector>`. */
|
|
9
|
+
export declare const SHARE_TARGETS: readonly ["email", "slack", "browser"];
|
|
10
|
+
/** Whether an id can name a share target at all; which ones a runtime offers it says itself. */
|
|
11
|
+
export declare function isShareTargetId(id: string): boolean;
|
|
12
|
+
export type ShareLang = Lang;
|
|
13
|
+
export type ShareIcon = "mail" | "folder" | "chat" | "plug" | "globe";
|
|
14
|
+
/** One input of a target's form. */
|
|
15
|
+
export interface ShareField {
|
|
16
|
+
id: string;
|
|
17
|
+
label: string;
|
|
18
|
+
/** `emails`: one or more addresses. `select`: one of `options`, or read from the account. */
|
|
19
|
+
kind: "text" | "textarea" | "emails" | "url" | "select";
|
|
20
|
+
required?: boolean;
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
help?: string;
|
|
23
|
+
options?: ShareChoice[];
|
|
24
|
+
/** select: the choices come from the connected account (channels, folders) and are loaded then. */
|
|
25
|
+
fromAccount?: boolean;
|
|
26
|
+
/** What the form starts with. */
|
|
27
|
+
value?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ShareChoice {
|
|
30
|
+
value: string;
|
|
31
|
+
label: string;
|
|
32
|
+
}
|
|
33
|
+
/** A ready-made filling of a target's form, e.g. "LinkedIn" for the browser. */
|
|
34
|
+
export interface SharePreset {
|
|
35
|
+
label: string;
|
|
36
|
+
values: Record<string, string>;
|
|
37
|
+
}
|
|
38
|
+
/** A share target as the person picks it on a result. */
|
|
39
|
+
export interface ShareTargetView {
|
|
40
|
+
/** Unique among the targets of one result: the target's id, or `<n>:<id>` for one the wizard defines. */
|
|
41
|
+
key: string;
|
|
42
|
+
target: string;
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
icon: ShareIcon;
|
|
46
|
+
/** The account it sends with; null = none needed. */
|
|
47
|
+
connection: ConnectionView | null;
|
|
48
|
+
fields: ShareField[];
|
|
49
|
+
/** What of the result it takes: files the person picks, or the link to the result page. */
|
|
50
|
+
takes: "files" | "link";
|
|
51
|
+
/** An agent does the work: it takes a while, may ask for a sign-in, and uses the wizard's credits. */
|
|
52
|
+
agent: boolean;
|
|
53
|
+
presets: SharePreset[];
|
|
54
|
+
}
|
|
55
|
+
/** One file to send: a deliverable of the result in one of its formats. */
|
|
56
|
+
export interface ShareItem {
|
|
57
|
+
/** A step id, or `lists.<id>`. */
|
|
58
|
+
from: string;
|
|
59
|
+
format: Format;
|
|
60
|
+
}
|
|
61
|
+
/** What the person sends off. */
|
|
62
|
+
export interface ShareRequest {
|
|
63
|
+
/** `key` of the target. */
|
|
64
|
+
target: string;
|
|
65
|
+
items: ShareItem[];
|
|
66
|
+
values: Record<string, string>;
|
|
67
|
+
lang?: ShareLang;
|
|
68
|
+
}
|
|
69
|
+
export type ShareJobStatus = "running" | "done" | "failed" | "cancelled";
|
|
70
|
+
/** One result on its way to one target, or arrived there. */
|
|
71
|
+
export interface ShareJobView {
|
|
72
|
+
id: string;
|
|
73
|
+
target: string;
|
|
74
|
+
/** The target's name when it was sent. */
|
|
75
|
+
name: string;
|
|
76
|
+
icon: ShareIcon;
|
|
77
|
+
status: ShareJobStatus;
|
|
78
|
+
/** What happened so far, oldest first. */
|
|
79
|
+
events: {
|
|
80
|
+
at: string;
|
|
81
|
+
message: string;
|
|
82
|
+
}[];
|
|
83
|
+
/** What the target asks the person right now: a sign-in, or leave to publish. */
|
|
84
|
+
ask: RunAsk | null;
|
|
85
|
+
/** Where it ended up, in words, with a link when there is one. */
|
|
86
|
+
result: {
|
|
87
|
+
summary: string;
|
|
88
|
+
url: string | null;
|
|
89
|
+
} | null;
|
|
90
|
+
error: string | null;
|
|
91
|
+
createdAt: string;
|
|
92
|
+
}
|
|
93
|
+
/** `GET /api/runs/<id>/share/targets`. */
|
|
94
|
+
export interface ShareOverview {
|
|
95
|
+
targets: ShareTargetView[];
|
|
96
|
+
/** Earlier jobs of this run, newest first. */
|
|
97
|
+
jobs: ShareJobView[];
|
|
98
|
+
}
|
|
99
|
+
/** A share target as the editor lists it for a wizard's result: what it is and what its form takes. */
|
|
100
|
+
export interface ShareTargetInfo {
|
|
101
|
+
id: string;
|
|
102
|
+
name: string;
|
|
103
|
+
description: string;
|
|
104
|
+
icon: ShareIcon;
|
|
105
|
+
agent: boolean;
|
|
106
|
+
/** Whether it can work on this server right now; a target that is not set up is not offered to people. */
|
|
107
|
+
usable: boolean;
|
|
108
|
+
/** A result that lists no targets offers it. */
|
|
109
|
+
byDefault: boolean;
|
|
110
|
+
fields: Pick<ShareField, "id" | "label" | "kind">[];
|
|
111
|
+
}
|
|
112
|
+
/** A target as the editor's preview shows it, with the placeholders that came out empty. */
|
|
113
|
+
export interface SharePreviewTarget extends ShareTargetView {
|
|
114
|
+
/** Placeholders of its prefilled fields that are empty in the run the preview is filled from. */
|
|
115
|
+
empty: string[];
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* `GET /api/studio/wizards/<id>/share-preview`: the draft's result page as a visitor or as the
|
|
119
|
+
* owner gets it, filled from the wizard's last finished test run.
|
|
120
|
+
*/
|
|
121
|
+
export interface SharePreview {
|
|
122
|
+
/** The test run the texts come from; null when none has finished. */
|
|
123
|
+
run: {
|
|
124
|
+
id: string;
|
|
125
|
+
at: string;
|
|
126
|
+
} | null;
|
|
127
|
+
targets: SharePreviewTarget[];
|
|
128
|
+
/** Targets of the result this audience does not get: an agent drives it, or it is not set up. */
|
|
129
|
+
left: {
|
|
130
|
+
name: string;
|
|
131
|
+
why: "agent" | "setup";
|
|
132
|
+
}[];
|
|
133
|
+
/** The start of each written deliverable in that run, by step id. */
|
|
134
|
+
outputs: Record<string, string>;
|
|
135
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sharing a finished result beyond the link and the downloads: a share target sends or publishes
|
|
3
|
+
* it — by e-mail, into a cloud folder, to a Slack channel, through a connector, on a website.
|
|
4
|
+
*/
|
|
5
|
+
/** The targets every runtime has. A connector adds `storage:<connector>` or `connector:<connector>`. */
|
|
6
|
+
export const SHARE_TARGETS = ["email", "slack", "browser"];
|
|
7
|
+
const CONNECTOR_TARGET = /^(storage|connector):[A-Za-z0-9][A-Za-z0-9_.-]{0,80}$/;
|
|
8
|
+
/** Whether an id can name a share target at all; which ones a runtime offers it says itself. */
|
|
9
|
+
export function isShareTargetId(id) {
|
|
10
|
+
return SHARE_TARGETS.includes(id) || CONNECTOR_TARGET.test(id);
|
|
11
|
+
}
|
|
@@ -60,6 +60,14 @@ export interface ConnectionDef {
|
|
|
60
60
|
policy?: Record<string, "allow" | "ask">;
|
|
61
61
|
title?: string;
|
|
62
62
|
description?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Share targets only (never in a wizard definition): the connectors the person can pick from,
|
|
65
|
+
* and the provider is asked for no more than `actions` need — a target that sends never asks
|
|
66
|
+
* for the right to read.
|
|
67
|
+
*/
|
|
68
|
+
target?: {
|
|
69
|
+
connectors: string[];
|
|
70
|
+
};
|
|
63
71
|
}
|
|
64
72
|
/** A connector the person can pick for a connection: an OAuth sign-in or a credentials form. */
|
|
65
73
|
export interface ConnectorOption {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@engenty/wizards-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.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. The runtime, which `npx wizards` installs.",
|
|
5
5
|
"license": "FSL-1.1-MIT AND CC-BY-4.0",
|
|
6
6
|
"homepage": "https://engenty.ai",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"mammoth": "1.13.0",
|
|
62
62
|
"marked": "18.0.14",
|
|
63
63
|
"nanoid": "5.1.16",
|
|
64
|
+
"nodemailer": "10.0.9",
|
|
64
65
|
"pdf-parse": "2.4.5",
|
|
65
66
|
"playwright-core": "1.63.0",
|
|
66
67
|
"postal-mime": "4.0.2",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wizards",
|
|
3
3
|
"displayName": "engenty wizards",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.0",
|
|
5
5
|
"description": "Build page-by-page AI wizards that people open on a shared link — designed, tested and published from Claude Code — run your published ones in the chat, and keep them in a pane beside it.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "engenty"
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: The wizard format
|
|
3
|
-
description: A wizard as JSON and as a .wizard file, its JSON Schema, and checking it with wizards validate.
|
|
4
|
-
version: 0.5.13
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
A wizard is one JSON document, its **definition**. The studio exports it as a `.wizard` file
|
|
8
|
-
and imports one back. You can write either by hand or with a tool, check it in your editor
|
|
9
|
-
against a JSON Schema, and check it completely with `wizards validate`.
|
|
10
|
-
|
|
11
|
-
The code that defines the format and checks it is also under the
|
|
12
|
-
[MIT licence](https://github.com/engenty/wizards/blob/main/packages/shared/LICENSE-MIT), so any
|
|
13
|
-
tool may read and write wizards.
|
|
14
|
-
|
|
15
|
-
## The definition
|
|
16
|
-
|
|
17
|
-
```json
|
|
18
|
-
{
|
|
19
|
-
"$schema": "https://engenty.ai/schema/v1/wizard.json",
|
|
20
|
-
"version": 1,
|
|
21
|
-
"title": "Create an invoice",
|
|
22
|
-
"description": "A finished invoice from a few details.",
|
|
23
|
-
"avatar": "round",
|
|
24
|
-
"lang": "en",
|
|
25
|
-
"steps": [ … ]
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
`steps` run from top to bottom, and the last one is always a `result` step. The schema below
|
|
30
|
-
lists the step types and their fields. The studio’s MCP tool `get_authoring_guide` explains them
|
|
31
|
-
with a complete example.
|
|
32
|
-
|
|
33
|
-
`lang` is the language the wizard speaks to people, as a two-letter code: `en`, `de`, `it`, `fr`
|
|
34
|
-
and so on. The schema checks the shape of the code; `wizards validate` and the studio check that
|
|
35
|
-
it names a real language. It sets the runner’s own words and how numbers and dates are written.
|
|
36
|
-
Without it, the language is read from the wizard’s own words, and English is the default where
|
|
37
|
-
they are not clearly German.
|
|
38
|
-
|
|
39
|
-
`version` is the definition’s version. It changes only with a breaking change; the schemas of
|
|
40
|
-
each version stay online in their own folder (`/schema/v1/`, `/schema/v2/`, …).
|
|
41
|
-
|
|
42
|
-
## The `.wizard` file
|
|
43
|
-
|
|
44
|
-
The file is a zip with two things in it:
|
|
45
|
-
|
|
46
|
-
| Path | What it holds |
|
|
47
|
-
|---|---|
|
|
48
|
-
| `wizard.json` | The manifest: the definition, plus what the wizard needs from its space |
|
|
49
|
-
| `files/…` | The wizard’s workspace: widget pages, templates, images. At most 200 files and 25 MB |
|
|
50
|
-
| `files/knowledge/…` | Only when the export was asked for it: the space’s Knowledge pages as Markdown files, one per page, with its title in front. A website runs the wizard with them, without the space |
|
|
51
|
-
|
|
52
|
-
```json
|
|
53
|
-
{
|
|
54
|
-
"$schema": "https://engenty.ai/schema/v1/wizard-package.json",
|
|
55
|
-
"format": "engenty-wizard",
|
|
56
|
-
"version": 1,
|
|
57
|
-
"definition": { … },
|
|
58
|
-
"connectors": [{ "id": "billomat", "name": "Billomat", "domain": "billomat.com" }],
|
|
59
|
-
"mcpServers": [{ "id": "notion", "name": "Notion" }]
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
`connectors` and `mcpServers` (the space’s connected systems) name what the wizard’s steps use
|
|
64
|
-
from its space, without addresses or credentials. When the space you import into lacks one, the
|
|
65
|
-
import says so.
|
|
66
|
-
|
|
67
|
-
`knowledge` (`{ "pages": 12, "truncated": false }`) is there when the export took the space’s
|
|
68
|
-
pages along. It says how many there are and whether the cap of about 2 MB left some out. The
|
|
69
|
-
share dialog’s website package does this with “Take the knowledge along”.
|
|
70
|
-
|
|
71
|
-
The import also takes a `wizard.json` on its own, or a definition on its own.
|
|
72
|
-
The file’s media type is `application/vnd.engenty.wizard+zip`.
|
|
73
|
-
|
|
74
|
-
## JSON Schema
|
|
75
|
-
|
|
76
|
-
| For | Schema |
|
|
77
|
-
|---|---|
|
|
78
|
-
| A definition | [`https://engenty.ai/schema/v1/wizard.json`](https://engenty.ai/schema/v1/wizard.json) |
|
|
79
|
-
| `wizard.json` in a package | [`https://engenty.ai/schema/v1/wizard-package.json`](https://engenty.ai/schema/v1/wizard-package.json) |
|
|
80
|
-
|
|
81
|
-
Put the address under `"$schema"`, and editors such as VS Code complete keys and mark mistakes
|
|
82
|
-
as you type. The studio’s export writes it into every `wizard.json`.
|
|
83
|
-
|
|
84
|
-
The schemas are written from the code that reads wizards, so they match it. They are stricter
|
|
85
|
-
in one way: a key the app does not know is an error. The app would drop such a key without a
|
|
86
|
-
word.
|
|
87
|
-
|
|
88
|
-
`wizards validate` checks what a JSON Schema cannot say: unique ids, steps and fields that refer
|
|
89
|
-
to each other, templates that name answers that exist by then, and files in the workspace.
|
|
90
|
-
|
|
91
|
-
## `wizards validate`
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
wizards validate invoice.wizard
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
It checks a wizard the way the studio’s import does, without a running studio and without an
|
|
98
|
-
account. It takes any number of paths:
|
|
99
|
-
|
|
100
|
-
| Path | Read as |
|
|
101
|
-
|---|---|
|
|
102
|
-
| `invoice.wizard` | A package |
|
|
103
|
-
| `invoice/` or `invoice/wizard.json` | An unpacked package, its workspace under `invoice/files/` |
|
|
104
|
-
| `invoice.json` | A definition on its own, or a `wizard.json` |
|
|
105
|
-
|
|
106
|
-
```text
|
|
107
|
-
✗ invoice.json 2 issues
|
|
108
|
-
The last step must be a result step.
|
|
109
|
-
"{{nope}}" refers to a field that is not asked before "g".
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
A wizard without issues gets a ✓ with its number of steps and files. `--json` prints the
|
|
113
|
-
results as JSON. The exit code is `0` when every wizard is fine, `1` when one has issues and `2`
|
|
114
|
-
when no path was given. That is enough for a check in CI:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
npx wizards validate wizards/*.wizard
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
`npx wizards` installs engenty wizards into `~/.engenty/wizards` first, the first time. To check
|
|
121
|
-
without an install, on Node.js 24.11 or newer, run the runtime from npm directly:
|
|
122
|
-
`npx -p @engenty/wizards-runtime wizards validate wizards/*.wizard`.
|
|
123
|
-
|
|
124
|
-
The import checks what belongs to the space, because only the space has it: its connectors and
|
|
125
|
-
their actions, its connected systems (MCP servers) and its plugins’ tools.
|
|
@@ -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{Bt as r,Cr as i,Ht as a,Qt as o,Vt as s,Xt as c,_r as l,an as u,qn as d,qt as f,zt as p}from"./ui-DMmT-cSO.js";import{t as m}from"./preload-helper-CNEI7N0N.js";import{Ot as h,Q as g,X as _,Z as v}from"./index-4jH2mkp7.js";import{c as y,f as b}from"./settings-menu-Dpkp3f56.js";import{ReleaseNotes as x,loadReleases as S,releaseDate as C,releaseLabel as w}from"./ChangelogDialog-CZrd-MgC.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:`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:r,description:i}){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)(l,{"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:r})]}),i?(0,O.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:i}):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:u(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),[i,o]=(0,T.useState)(``);(0,T.useEffect)(()=>{if(!e||t)return;let r=!1;return m(()=>import(`./oss-credits-Bc05Qv5H.js`).then(e=>{r||n(e.default)}),[]),()=>{r=!0}},[e,t]),(0,T.useEffect)(()=>{e||o(``)},[e]);let s=i.trim().toLowerCase(),c=e=>s?e.filter(e=>k(s,e.name,e.license,u(e.description))):e,l=e=>s?e.filter(e=>k(s,e.name,e.license,e.version)):e,d=c(E),p=c(D),h=t?[{id:`shared`,label:u(`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=d.length===0&&p.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:u(`about.creditsHint`)}),(0,O.jsx)(a,{type:`search`,value:i,placeholder:u(`about.search`),onChange:e=>o(e.target.value)}),d.length>0?(0,O.jsx)(j,{title:u(`about.creditsProduct`),children:(0,O.jsx)(M,{credits:d})}):null,p.length>0?(0,O.jsx)(j,{title:u(`about.creditsBuiltWith`),children:(0,O.jsx)(M,{credits:p})}):null,t===null?(0,O.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,O.jsx)(f,{})}):h.length>0?(0,O.jsx)(j,{title:u(`about.creditsDeps`),hint:s?void 0:u(`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)(r,{children:u(`about.noMatches`)}):null]})}var F=[`new`,`earlier`,`credits`],I=e=>u(e===`new`?`about.tab.new`:e===`earlier`?`about.tab.earlier`:`about.credits`),L=e=>e===1?u(`about.change`):u(`about.changes`,{n:e});function R({open:e,onClose:t,me:n}){let r=n?.mode===`local`,{data:a,latest:l}=g(r&&e),[m,E]=(0,T.useState)(null),[D,k]=(0,T.useState)(`new`),A=b(F.indexOf(D)),j=a?.newer&&l?l:v;(0,T.useEffect)(()=>{if(!e)return;let t=!1;return E(null),S(j===`0.7.11`?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?a?.kind??null:`cloud`;return(0,O.jsxs)(p,{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)(s,{label:u(`common.close`),onClick:t,children:(0,O.jsx)(d,{className:`size-4`})})}),(0,O.jsxs)(`div`,{className:`flex flex-col items-center pt-4 text-center`,children:[(0,O.jsx)(h,{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:[u(`about.version`,{v}),R?` · ${u(`about.kind.${R}`)}`:``]})]}),r?(0,O.jsx)(`div`,{className:`mt-5`,children:(0,O.jsx)(_,{enabled:e})}):null,(0,O.jsx)(`div`,{className:`mt-6 flex justify-center`,children:(0,O.jsx)(c,{value:D,onChange:k,options:F.map(e=>({id:e,label:I(e)})),label:u(`about.title`)})}),(0,O.jsxs)(`div`,{className:o(`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)(f,{})}):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:u(`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)(i,{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,An as a,Bn as o,Dt as s,Er as c,Et as l,Jn as u,Kn as d,Nr as f,Qn as p,Qt as m,Tt as h,Vt as g,W as _,Wr as v,Wt as y,Xn as b,Zn as x,Zt as S,_t as C,an as w,ar as T,bt as E,cn as D,cr as O,ct as k,en as A,gn as j,gt as ee,ht as M,kr as N,lt as P,m as F,pt as I,qt as L,st as te,tr as R,ur as z,vt as ne,wt as re,yt as ie}from"./ui-DMmT-cSO.js";import{t as ae}from"./phone-BjmhIKuT.js";import{At as oe,Ct as se,Ht as ce,at as le,it as ue,ot as de,t as fe,zt as pe}from"./index-4jH2mkp7.js";import{n as me}from"./RunnerView-BW1h4x63.js";var he={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`}]]};he.node;var ge=f(he),_e={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`}]]};_e.node;var ve=f(_e),ye={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`}]]};ye.node;var be=f(ye),xe={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`}]]};xe.node;var Se=f(xe),Ce=v(),B=e(t(),1),V=e(n(),1),we=typeof window<`u`&&window.matchMedia(`(pointer: coarse)`).matches;function Te({since:e}){let[t,n]=(0,B.useState)(Date.now());if((0,B.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,V.jsxs)(`span`,{className:`font-mono text-[0.8125rem] text-white/60 tabular-nums`,children:[i,`:`,a]})}function H({label:e,on:t,danger:n,busy:r,onClick:i,children:a}){return(0,V.jsx)(`button`,{type:`button`,"aria-label":e,title:e,"aria-pressed":t,disabled:r,onClick:i,className:m(`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,V.jsx)(L,{className:`size-5`}):a})}function Ee({voice:e}){let t=(0,B.useRef)(null),{captions:n}=e;return(0,B.useEffect)(()=>{n.length&&t.current?.scrollIntoView({block:`end`})},[n]),n.length?(0,V.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 sm:px-5`,children:(0,V.jsxs)(`ol`,{className:`mx-auto flex max-w-[720px] flex-col gap-2 py-2`,children:[n.map(e=>(0,V.jsx)(`li`,{className:m(`text-[0.9375rem] leading-snug`,e.who===`bot`?`text-white/95`:`text-right text-white/50`),children:e.text},e.id)),(0,V.jsx)(`div`,{ref:t})]})}):null}function De({voice:e,view:t,video:n,className:r}){let i=e.state===`live`,a=e.state===`connecting`,[o,s]=(0,B.useState)(null),[c,l]=(0,B.useState)(!1);(0,B.useEffect)(()=>{s(i?Date.now():null)},[i]);let d=async()=>{l(!1),await e.start(),n&&await e.startCamera()},f=()=>{e.stop(),l(!0)},p=n||e.camera,h=[...e.captions].reverse().find(e=>e.who===`bot`),g=[...e.captions].reverse().find(e=>e.who===`me`),_=e.speaking?w(`talk.speaking`):e.listening?w(`talk.listening`):i?w(`talk.live`):a?w(`talk.connecting`):c?w(`video.ended`):``;return(0,V.jsxs)(`section`,{className:m(`relative flex min-h-0 flex-col bg-neutral-950 text-white`,`safe-top`,r),children:[(0,V.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 px-4 sm:px-5`,children:[(0,V.jsx)(`div`,{className:`min-w-0 flex-1 truncate font-display font-semibold text-[1rem] tracking-tight`,children:t?.wizard.title??``}),_?(0,V.jsxs)(`span`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-white/70`,children:[i?(0,V.jsx)(`span`,{className:m(`size-2 rounded-full`,e.speaking?`animate-pulse-dot bg-emerald-400`:`bg-rose`)}):null,_]}):null,(0,V.jsx)(Te,{since:o})]}),(0,V.jsxs)(`div`,{className:m(`grid min-h-0 gap-2 px-3 pb-2 sm:px-4`,p?`flex-1 grid-cols-1 sm:grid-cols-2`:`shrink-0 grid-cols-1`,!p&&i&&e.captions.length?`h-[38%]`:p?``:`flex-1`),children:[(0,V.jsxs)(`div`,{className:m(`relative min-h-0 overflow-hidden rounded-2xl bg-neutral-900`,!p&&`hidden`),children:[(0,V.jsx)(`video`,{ref:e.video,muted:!0,playsInline:!0,autoPlay:!0,className:m(`absolute inset-0 h-full w-full object-cover`,e.facing===`user`&&`-scale-x-100`,e.camera?`block`:`hidden`)}),e.camera?null:(0,V.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/50`,children:[(0,V.jsx)(be,{className:`size-8`}),(0,V.jsx)(`span`,{className:`text-[0.8125rem]`,children:w(`video.cameraOff`)})]}),(0,V.jsxs)(`span`,{className:`absolute bottom-2 left-3 rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:[w(`video.you`),e.muted?(0,V.jsx)(ce,{className:`ml-1.5 inline size-3`}):null]})]}),(0,V.jsxs)(`div`,{className:m(`relative flex min-h-0 items-center justify-center overflow-hidden rounded-2xl transition-shadow`,p?`bg-neutral-900`:`bg-transparent`,p&&e.speaking&&`ring-2 ring-emerald-400/70`),children:[(0,V.jsx)(`div`,{className:m(`rounded-full transition-shadow duration-500`,!p&&e.listening&&`shadow-[0_0_80px_20px_rgba(244,63,94,0.25)]`,!p&&e.speaking&&`shadow-[0_0_80px_20px_rgba(52,211,153,0.3)]`,e.speaking&&`animate-breathe`),children:(0,V.jsx)(se,{kind:t?.wizard.avatar??`round`,size:p?140:200,fluffy:!0,interactive:!1})}),p?(0,V.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&&!p?(0,V.jsx)(Ee,{voice:e}):i&&(h||g)?(0,V.jsx)(`div`,{className:`shrink-0 px-4 pb-2 sm:px-5`,children:(0,V.jsxs)(`div`,{className:`mx-auto max-w-[720px] space-y-1 text-center`,children:[g?(0,V.jsx)(`p`,{className:`line-clamp-1 text-[0.8125rem] text-white/50`,children:g.text}):null,h?(0,V.jsx)(`p`,{className:`line-clamp-3 text-[0.9375rem] text-white/95 leading-snug`,children:h.text}):null]})}):null,e.error?(0,V.jsx)(`p`,{className:`shrink-0 px-5 pb-2 text-center text-[0.8125rem] text-rose`,children:e.error}):null,(0,V.jsx)(`div`,{className:`flex shrink-0 items-center justify-center gap-3 px-4 pt-1 pb-4`,children:i?(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(H,{label:w(e.muted?`video.unmute`:`video.mute`),on:!e.muted,onClick:e.toggleMute,children:e.muted?(0,V.jsx)(ce,{className:`size-5`}):(0,V.jsx)(z,{className:`size-5`})}),(0,V.jsx)(H,{label:w(e.camera?`talk.cameraOff`:`talk.camera`),on:e.camera,onClick:()=>e.camera?e.stopCamera():void e.startCamera(),children:e.camera?(0,V.jsx)(u,{className:`size-5`}):(0,V.jsx)(be,{className:`size-5`})}),e.camera&&we?(0,V.jsx)(H,{label:w(`video.flip`),onClick:()=>void e.flipCamera(),children:(0,V.jsx)(b,{className:`size-5`})}):null,(0,V.jsx)(H,{label:w(`video.leave`),danger:!0,onClick:f,children:(0,V.jsx)(pe,{className:`size-5`})})]}):(0,V.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[(0,V.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,V.jsx)(L,{className:`size-4`}):n?(0,V.jsx)(u,{className:`size-5`}):(0,V.jsx)(z,{className:`size-5`}),w(c?`video.rejoin`:n?`video.join`:`talk.start`)]}),!c&&!e.error?(0,V.jsx)(`p`,{className:`max-w-sm text-center text-[0.75rem] text-white/50`,children:w(n?`video.hint`:`talk.joinHint`)}):null]})})]})}var Oe=e=>j[e.kind]!==`device`,ke=1024,Ae=4e3;function je(e,t){return e?e.length>t?`${e.slice(0,t)} …`:e:``}function Me(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: ${i(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}: ${je(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=Oe(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?` = ${je(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}": ${je(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 Ne(e,t,n,r){let[i,a]=(0,B.useState)(`off`),[o,s]=(0,B.useState)(null),[c,l]=(0,B.useState)(!1),[u,d]=(0,B.useState)(!1),[f,p]=(0,B.useState)(!1),[m,h]=(0,B.useState)(`environment`),[g,v]=(0,B.useState)(!1),[y,b]=(0,B.useState)([]),x=(0,B.useRef)(null),S=(0,B.useRef)(null),C=(0,B.useRef)(0),T=(0,B.useRef)(!1);T.current=f;let E=(0,B.useRef)(null),D=(0,B.useRef)(null),O=(0,B.useRef)(null),k=(0,B.useRef)(null),A=(0,B.useRef)(t);A.current=t;let j=(0,B.useRef)(r);j.current=r;let ee=(0,B.useRef)(n);ee.current=n;let M=(0,B.useRef)(``),N=(0,B.useCallback)(e=>{let t=D.current;t&&t.readyState===`open`&&t.send(JSON.stringify(e))},[]),P=(0,B.useCallback)(()=>{let e=x.current;if(!T.current||!e||e.videoWidth===0)return null;let t=Math.min(1,ke/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)},[]),F=(0,B.useCallback)(()=>{for(let e of S.current?.getTracks()??[])e.stop();S.current=null,x.current&&(x.current.srcObject=null),p(!1)},[]),I=(0,B.useCallback)(async e=>{if(S.current)return;let t=e??`environment`;try{let e=await navigator.mediaDevices.getUserMedia({video:{facingMode:{ideal:t},width:{ideal:1280}},audio:!1});S.current=e;let n=e.getVideoTracks()[0]?.getSettings().facingMode;h(n===`user`||n===`environment`?n:t),x.current&&(x.current.srcObject=e,await x.current.play().catch(()=>void 0)),p(!0)}catch(e){s(e.name===`NotAllowedError`?w(`talk.cameraDenied`):e.message)}},[]),L=(0,B.useCallback)(async()=>{let e=m===`user`?`environment`:`user`;F(),await I(e)},[m,F,I]),te=(0,B.useCallback)(()=>{v(e=>{for(let t of k.current?.getAudioTracks()??[])t.enabled=e;return!e})},[]),R=(0,B.useCallback)(()=>{F(),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),M.current=``,l(!1),d(!1),v(!1),a(`off`)},[F]);(0,B.useEffect)(()=>()=>R(),[R]);let z=(0,B.useCallback)(async(t,n)=>{let r=A.current,i=j.current,a=ee.current;switch(t){case`get_state`:return r?Me(r,i,T.current):`no run`;case`look`:{let e=P();return e?(N({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=P();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 _.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&&Oe(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 _.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,P,N]),ne=(0,B.useCallback)(async()=>{if(!E.current){s(null),b([]),a(`connecting`);try{let t=await _.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()-C.current>Ae?P():null;e&&(C.current=Date.now(),N({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{}z(e,r).then(e=>{N({type:`conversation.item.create`,item:{type:`function_call_output`,call_id:n,output:e}}),N({type:`response.create`})});break}case`error`:s(String(t.error?.message??`error`))}},o.onopen=()=>{a(`live`);let e=A.current;e&&(M.current=Me(e,j.current,T.current),N({type:`conversation.item.create`,item:{type:`message`,role:`user`,content:[{type:`input_text`,text:`[state]\n${M.current}\n\nGreet the person in one sentence and ask the first open field.`}]}}),N({type:`response.create`}))},o.onclose=()=>{E.current===r&&R()};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(`${w(`talk.failed`)} (${u.status})`);await r.setRemoteDescription({type:`answer`,sdp:await u.text()})}catch(e){R(),s(e.name===`NotAllowedError`?w(`chat.micDenied`):e.message),a(`error`)}}},[e,z,P,N,R]);return(0,B.useEffect)(()=>{if(i!==`live`||!t)return;let e=Me(t,r,f);if(e===M.current)return;let n=M.current;M.current=e,N({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])&&N({type:`response.create`})},[i,t,r,f,N]),{state:i,error:o,speaking:c,listening:u,start:ne,stop:R,camera:f,facing:m,startCamera:I,stopCamera:F,flipCamera:L,muted:g,toggleMute:te,captions:y,video:x}}var U=(e,t,n)=>({key:e,who:`bot`,node:t,...n}),W=(e,t,n)=>({key:e,who:`me`,node:t,...n}),Pe=(0,B.createContext)(null),G=(0,B.createContext)(null);function Fe(){return(0,B.useContext)(G)?.voice??null}function K({children:e}){let t=(0,B.useContext)(Pe);return t?(0,Ce.createPortal)(e,t):null}function q({header:e,footer:t,children:n}){let[r,i]=(0,B.useState)(null),a=(0,B.useRef)(null),o=(0,B.useRef)(null),s=(0,B.useRef)(!0);return(0,B.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,V.jsx)(Pe.Provider,{value:r,children:(0,V.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[e,(0,V.jsx)(`div`,{ref:a,className:`min-h-0 flex-1 overflow-y-auto overscroll-contain`,children:(0,V.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,V.jsxs)(`div`,{className:`shrink-0 border-border-soft border-t bg-background`,onPointerDownCapture:()=>{s.current=!0},onKeyDownCapture:()=>{s.current=!0},children:[(0,V.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,B.useContext)(G),r=(0,B.useMemo)(()=>t.map(e=>({key:e.key,who:e.who,spoken:!e.bare&&!e.wide})),[t]),i=(0,B.useCallback)(e=>{let t=document.querySelector(`[data-say="${CSS.escape(e)}"]`);return t?.querySelector(`[data-say-text]`)?.getAttribute(`data-say-text`)??t?.innerText??null},[]);de(!!n?.readAloud,n?.lang??A,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,V.jsxs)(`div`,{className:`flex items-start gap-2.5`,children:[(0,V.jsx)(`div`,{className:`sticky top-1 shrink-0 pt-0.5`,children:(0,V.jsx)(se,{kind:e,size:30,interactive:n>=a.length-2})}),(0,V.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-col items-start gap-1.5`,children:t.lines.map(e=>(0,V.jsx)(`div`,{"data-anchor":e.anchor?``:void 0,"data-say":e.key,className:m(`animate-rise`,e.bare?`w-full pt-1`:`rounded-2xl rounded-tl-md text-[0.9375rem] text-ink leading-relaxed`,!e.bare&&(e.wide?m(`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,V.jsxs)(`div`,{className:`flex animate-rise flex-col items-end gap-1 pl-10`,children:[(0,V.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,V.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,V.jsx)(T,{className:`size-3`}),` `,w(`chat.change`)]}):null]},e.key)))}function Ie(){return(0,V.jsx)(`span`,{className:`inline-flex items-center gap-1 py-1.5`,role:`status`,"aria-label":w(`run.working`),children:[0,1,2].map(e=>(0,V.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,V.jsx)(`div`,{className:`flex flex-wrap items-center gap-2`,children:e})}var X=(e,t)=>U(e,(0,V.jsx)(Y,{children:t}),{bare:!0});function Z({onClick:e,children:t,primary:n,on:r,disabled:i,busy:a}){return(0,V.jsxs)(`button`,{type:`button`,"aria-pressed":r,disabled:i||a,onClick:e,className:m(`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,V.jsx)(L,{className:`size-4`}):null,t]})}function Le({initial:e=``,placeholder:t,multiline:n,inputProps:r,busy:i,disabled:a,inputRef:o,onSend:s}){let[c,l]=(0,B.useState)(e),d=(0,B.useRef)(null),f=o??d,p=(0,B.useContext)(G),h=F(c,l,{endpoint:p?`/api/runs/${p.runId}/transcribe`:void 0}),_=!!p&&h.supported&&!a;(0,B.useEffect)(()=>{if(!_)return;let e=e=>{(e.metaKey||e.ctrlKey)&&e.shiftKey&&e.key.toLowerCase()===`m`&&(e.preventDefault(),h.toggle())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[_,h.toggle]),(0,B.useEffect)(()=>{!re&&!a&&f.current?.focus()},[a,f]);let v=()=>{i||a||(h.listening&&h.toggle(),s(c)!==!1&&l(``))},y=h.listening?w(`chat.listening`):h.processing?w(`chat.transcribing`):t,b=p?.voice??null,C=!!p?.call,T=p&&!C&&(ue||_||b)?(0,V.jsxs)(`div`,{className:`mb-1 flex shrink-0 items-center`,children:[b?(0,V.jsx)(g,{label:w(b.state===`live`?`talk.stop`:b.state===`connecting`?`talk.connecting`:`talk.start`),"aria-pressed":b.state===`live`,disabled:b.state===`connecting`,onClick:()=>b.state===`live`?b.stop():void b.start(),className:m(`size-9`,b.state===`live`&&`bg-rose-tint text-rose hover:bg-rose-tint hover:text-rose`,b.state===`off`&&p.talk&&`bg-primary text-primary-foreground hover:bg-primary`),children:b.state===`connecting`?(0,V.jsx)(L,{className:`size-4`}):b.state===`live`?(0,V.jsx)(pe,{className:`size-4`}):(0,V.jsx)(ae,{className:`size-4`})}):null,b?.state===`live`?(0,V.jsx)(g,{label:w(b.camera?`talk.cameraOff`:`talk.camera`),"aria-pressed":b.camera,onClick:()=>b.camera?b.stopCamera():void b.startCamera(),className:m(`size-9`,b.camera&&`text-ink`),children:b.camera?(0,V.jsx)(u,{className:`size-4`}):(0,V.jsx)(be,{className:`size-4`})}):null,ue?(0,V.jsx)(g,{label:w(p.readAloud?`chat.readAloudOff`:`chat.readAloud`),"aria-pressed":p.readAloud,onClick:()=>p.setReadAloud(!p.readAloud),className:m(`size-9`,p.readAloud&&`text-ink`),children:p.readAloud?(0,V.jsx)(oe,{className:`size-4`}):(0,V.jsx)(Se,{className:`size-4`})}):null,_?(0,V.jsx)(g,{label:w(h.listening?`chat.dictateStop`:`chat.dictate`),"aria-pressed":h.listening,disabled:h.processing,onClick:h.toggle,className:m(`size-9`,h.listening&&`bg-rose-tint text-rose hover:bg-rose-tint hover:text-rose`),children:h.processing?(0,V.jsx)(L,{className:`size-4`}):h.listening?(0,V.jsx)(x,{className:`size-3.5 animate-pulse-dot fill-current`}):(0,V.jsx)(z,{className:`size-4`})}):null]}):null;return(0,V.jsxs)(`form`,{className:`pb-3`,onSubmit:e=>{e.preventDefault(),v()},children:[b&&!C?(0,V.jsx)(`video`,{ref:b.video,muted:!0,playsInline:!0,autoPlay:!0,className:m(`mb-2 ml-auto w-32 rounded-xl bg-black object-cover shadow-soft ring-1 ring-border-soft`,b.camera?`block`:`hidden`)}):null,(0,V.jsxs)(`div`,{className:m(`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:[T,n?(0,V.jsx)(S,{ref:f,minRows:1,maxRows:6,value:c,disabled:a,placeholder:y,autoCapitalize:`sentences`,onChange:e=>l(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!re&&!e.nativeEvent.isComposing&&(e.preventDefault(),v())},className:`min-h-11 border-0 bg-transparent py-2.5 shadow-none focus:ring-0`}):(0,V.jsx)(`input`,{ref:f,...r,value:c,disabled:a,placeholder:y,enterKeyHint:`send`,onChange:e=>l(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,V.jsx)(`button`,{type:`submit`,"aria-label":w(`chat.send`),title:w(`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,V.jsx)(L,{className:`size-4`}):(0,V.jsx)(N,{className:`size-4`})})]}),h.error?(0,V.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-rose`,children:h.error===`denied`?w(`chat.micDenied`):h.error}):C?null:b?.error?(0,V.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-rose`,children:b.error}):b?.state===`live`?(0,V.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-ink-3`,children:b.speaking?w(`talk.speaking`):b.listening?w(`talk.listening`):w(`talk.live`)}):p?.talk&&b?.state===`off`?(0,V.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-ink-3`,children:w(`talk.hint`)}):null]})}function Q({placeholder:e=w(`chat.above`)}){return(0,V.jsx)(K,{children:(0,V.jsx)(Le,{disabled:!0,placeholder:e,onSend:()=>!1})})}function Re(e){let t=j[e.kind];return t===`typed`&&!e.scan?`typed`:t===`tapped`?`tapped`:`control`}var ze=e=>e==null||e===``||Array.isArray(e)&&e.length===0;function Be(e,t){let n=e.kind===`toggle`||e.kind===`connection`||e.kind===`list`;if(ze(t))return e.required&&!n?w(`chat.required`):null;let r=String(t).trim();if(e.kind===`email`&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r))return w(`chat.badEmail`);if(e.kind===`url`)try{new URL(r)}catch{return w(`chat.badUrl`)}return e.kind===`number`&&d(r)===null?w(`chat.badNumber`):Array.isArray(t)&&e.multiple&&e.min&&t.length<e.min?w(`run.filesMin`,{n:t.length,min:e.min}):null}function Ve(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 He({field:e}){return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`span`,{className:`font-medium`,children:e.label}),e.help?(0,V.jsx)(`span`,{className:`mt-0.5 block text-[0.8125rem] text-ink-3`,children:e.help}):null]})}function Ue({step:e,only:t}){return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`span`,{className:`font-medium`,children:e.title}),e.description?(0,V.jsx)(`span`,{className:`mt-0.5 block text-ink-2`,children:e.description}):null,t?.help?(0,V.jsx)(`span`,{className:`mt-1 block text-[0.8125rem] text-ink-3`,children:t.help}):null]})}function We({field:e,value:t,runId:n}){if(e.kind===`connection`)return(0,V.jsx)(V.Fragment,{children:typeof t==`string`&&t?t:w(`chat.connected`)});if(e.kind===`list`)return(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,V.jsx)(c,{className:`size-4`}),` `,w(`chat.checked`)]});if(e.kind===`toggle`)return(0,V.jsx)(V.Fragment,{children:w(t===!0?`run.yes`:`run.no`)});if(ze(t))return(0,V.jsx)(`span`,{className:`italic opacity-80`,children:w(`chat.skipped`)});switch(e.kind){case`multiselect`:return(0,V.jsx)(V.Fragment,{children:t.map(D).join(`, `)});case`select`:return(0,V.jsx)(V.Fragment,{children:D(String(t))});case`date`:{let e=new Date(`${String(t)}T00:00`);return(0,V.jsx)(V.Fragment,{children:Number.isNaN(e.getTime())?String(t):new Intl.DateTimeFormat(A,{dateStyle:`long`}).format(e)})}case`color`:return(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[(0,V.jsx)(`span`,{className:`size-4 rounded-full ring-1 ring-white/50`,style:{background:String(t)}}),String(t)]});case`image`:case`signature`:return(0,V.jsx)(`span`,{className:`-mx-1.5 flex flex-wrap gap-1.5`,children:(Array.isArray(t)?t:[String(t)]).map(t=>(0,V.jsx)(`img`,{src:r(`/api/runs/${n}/assets/${t}`),alt:``,className:m(`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,V.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,V.jsx)(O,{className:`size-4`}),` `,w(e===1?`chat.file`:`chat.files`,{n:e})]})}case`audio`:{let e=t.seconds;return(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,V.jsx)(z,{className:`size-4`}),` `,w(`chat.voice`),e?` · ${Math.round(e)} s`:``]})}case`location`:{let e=t;return(0,V.jsx)(V.Fragment,{children:e.label||`${e.lat?.toFixed(5)}, ${e.lng?.toFixed(5)}`})}case`items`:return(0,V.jsx)(V.Fragment,{children:w(`chat.rows`,{n:Array.isArray(t)?t.length:0})});default:return(0,V.jsx)(V.Fragment,{children:String(t)})}}function Ge(e,t,n,r,i,a){let o=[U(t,(0,V.jsx)(Ue,{step:e,only:a}))];for(let e of i)a||o.push(U(`${t}:${e.id}`,(0,V.jsx)(He,{field:e}))),o.push(W(`${t}:${e.id}:a`,(0,V.jsx)(We,{field:e,value:n[e.id],runId:r})));return o}var Ke=(e,t)=>e.fields.filter(e=>!e.when&&!a(e)||t[e.id]!==void 0&&t[e.id]!==null);function qe(e,t){let n=[];e.wizard.description&&n.push(U(`hello`,e.wizard.description)),e.wizard.intro&&n.push(U(`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(...Ge(r,i,e.values,e.id,Ke(r,e.values),t))}else r.type===`review`&&(n.push(U(i,(0,V.jsx)(`span`,{className:`font-medium`,children:r.title}))),n.push(W(`${i}:a`,w(`run.accept`))))}let r=n.at(-1);return t&&r?.who===`me`&&(n[n.length-1]={...r,onEdit:t}),n}function Je(e,t){return e.fields.filter(e=>!a(e)||t.decidedFields?.includes(e.id)).map(e=>t.options?.[e.id]?.length?{...e,options:t.options[e.id]}:e)}function Ye({view:e,run:t,step:n,before:r}){let i=(0,B.useMemo)(()=>Je(n,e),[n,e]),a=e.known??{},[s,c]=(0,B.useState)(()=>te(n,e)),[l,u]=(0,B.useState)(()=>n.fields.some(t=>e.values[t.id]!==void 0)?o(Je(n,e),e.known??{},te(n,e)).slice(0,-1).map(e=>e.id):[]),[d,f]=(0,B.useState)({}),[p,m]=(0,B.useState)(!1),[h,g]=(0,B.useState)(!1),_=o(i,a,s),v=_.filter(e=>l.includes(e.id)),y=_.find(e=>!l.includes(e.id)),b=i.length===1?i[0]:void 0,x=v.at(-1),S=x?()=>u(e=>e.filter(e=>e!==x.id)):void 0;(0,B.useEffect)(()=>{let e=Object.keys(t.fieldErrors),n=o(i,a,s),r=n.findIndex(t=>e.includes(t.id));r>=0&&(u(n.slice(0,r).map(e=>e.id)),f(t.fieldErrors))},[t.fieldErrors]);let C=e=>{t.submitPage(n.id,e).then(g)},T=(0,B.useContext)(G),E=(0,B.useRef)(s);E.current=s;let D=T?.bindPage,O=(0,B.useRef)(C);O.current=C,(0,B.useEffect)(()=>{if(!D)return;let e=o(i,a,s);return D({step:n,fields:e,values:s,setField:(t,n)=>{let r=e.find(e=>e.id===t);return r?Be(r,n)||(c(e=>({...e,[t]:n})),u(e=>e.includes(t)?e:[...e,t]),f({}),null):`no such field on this page`},submit:()=>O.current(E.current)}),()=>D(null)},[D,n,i,a,s]);let k=e=>{if(!y)return!1;let t=Be(y,e);if(t)return f({[y.id]:t}),!1;let n={...s,[y.id]:e},r=[...l,y.id];return c(n),u(r),f({}),o(i,a,n).some(e=>!r.includes(e.id))||C(n),!0},A=[...r.map(e=>l.length?{...e,onEdit:void 0}:e),...Ge(n,`now:${n.id}`,s,e.id,v,b).map((e,t,n)=>t===n.length-1&&e.who===`me`&&y?{...e,onEdit:S}:e)];y?(Re(y)===`control`?A.push(U(`now:${n.id}:${y.id}:control`,(0,V.jsx)(M,{field:y,value:s[y.id],values:s,runId:e.id,view:e,closed:e.closed?.[y.id],onChange:e=>c(t=>({...t,[y.id]:e})),onBusy:m}),{wide:!0})):b||A.push(U(`now:${n.id}:${y.id}`,(0,V.jsx)(He,{field:y}))),d[y.id]&&A.push(U(`now:${n.id}:${y.id}:error`,d[y.id],{tone:`error`}))):t.busy||h?A.push(U(`sending`,(0,V.jsx)(Ie,{}))):t.error&&A.push(U(`send-error`,t.error,{tone:`error`}));let j=(0,V.jsx)(Q,{});if(h||!y&&l.length>0&&t.busy)j=(0,V.jsx)(Q,{placeholder:w(`run.working`)});else if(!y)A.push(X(`now:${n.id}:go`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Z,{primary:!0,busy:t.busy,onClick:()=>C(s),children:n.cta||w(`run.next`)}),S?(0,V.jsx)(Z,{onClick:S,disabled:t.busy,children:w(`run.back`)}):null]})));else{let r=Re(y),i=!y.required&&y.kind!==`connection`&&y.kind!==`list`?(0,V.jsx)(Z,{onClick:()=>k(void 0),children:w(`chat.skip`)}):null;if(r===`typed`){i&&A.push(X(`now:${n.id}:${y.id}:replies`,i));let e=s[y.id];j=(0,V.jsx)(K,{children:(0,V.jsx)(Le,{initial:ze(e)?``:String(e),multiline:y.kind===`textarea`,placeholder:y.placeholder||(b?y.label:w(`chat.placeholder`)),inputProps:Xe(y),busy:t.busy,onSend:e=>k(Ve(y,e))},y.id)})}else if(r===`tapped`)A.push(U(`now:${n.id}:${y.id}:replies`,(0,V.jsx)(Ze,{field:y,view:e,value:s[y.id],onAnswer:k}),{bare:!0}));else{let e=_.filter(e=>!l.includes(e.id)).length===1;A.push(X(`now:${n.id}:${y.id}:replies`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Z,{primary:!0,disabled:p,onClick:()=>k(s[y.id]),children:e&&n.cta?n.cta:w(`chat.send`)}),i]})))}}return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(J,{avatar:e.wizard.avatar,lines:A}),j]})}function Xe(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 ee(e)}}function Ze({field:e,view:t,value:n,onAnswer:r}){let i=new Set(t.closed?.[e.id]?.values.map(String)),[a,o]=(0,B.useState)(Array.isArray(n)?n:[]);if(e.kind===`toggle`)return(0,V.jsxs)(Y,{children:[(0,V.jsx)(Z,{on:n===!1,disabled:i.has(`false`),onClick:()=>r(!1),children:w(`run.no`)}),(0,V.jsx)(Z,{on:n===!0,disabled:i.has(`true`),onClick:()=>r(!0),children:w(`run.yes`)})]});let s=e.options??[];return e.kind===`multiselect`?(0,V.jsxs)(Y,{children:[s.map(e=>(0,V.jsx)(Z,{on:a.includes(e),onClick:()=>o(t=>t.includes(e)?t.filter(t=>t!==e):s.filter(n=>n===e||t.includes(n))),children:D(e)},e)),(0,V.jsx)(Z,{primary:!0,disabled:e.required&&!a.length,onClick:()=>r(a),children:a.length||e.required?w(`chat.send`):w(`chat.skip`)})]}):(0,V.jsxs)(Y,{children:[s.map(e=>(0,V.jsx)(Z,{on:n===e,disabled:i.has(e),onClick:()=>r(e),children:D(e)},e)),e.required?null:(0,V.jsx)(Z,{onClick:()=>r(void 0),children:w(`chat.skip`)})]})}function Qe({view:e}){let t=(0,B.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(),[a,o]=(0,B.useState)(Date.now());(0,B.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(et),u=[...new Set(s.map(e=>e.asset).filter(e=>!!e))];return(0,V.jsxs)(`div`,{className:m(`flex max-w-full flex-col gap-1`,l?`w-full`:`w-96`),"data-say-text":t?.message??e.step?.title??w(`run.working`),children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,V.jsx)(Ie,{}),(0,V.jsx)(`span`,{className:`font-medium`,children:t?.message??e.step?.title??w(`run.working`)}),(0,V.jsx)(`span`,{className:`text-[0.75rem] text-ink-4 tabular-nums`,children:w(`run.elapsed`,{s:Math.max(0,Math.round((a-n)/1e3))})})]}),c&&c!==l?(0,V.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-ink-3`,children:[(0,V.jsx)(p,{className:`size-3.5 shrink-0 animate-breathe text-ember`}),(0,V.jsx)(`span`,{className:`truncate`,children:i(c)})]}):null,l&&e.status===`running`?(0,V.jsx)(nt,{runId:e.id,event:l}):null,u.length?(0,V.jsx)(`div`,{className:`mt-1.5 flex flex-wrap gap-1.5`,children:u.slice(-6).map(t=>(0,V.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 $e=new Set([`opens`,`clicks`,`clicksOn`,`types`,`typesText`,`selects`,`scrolls`,`presses`,`goesBack`,`waitsForPage`,`fastLoop`,`looksAtPage`,`personDrives`,`agentDrives`]);function et(e){return!!e.note&&$e.has(e.note.code)}var tt=1e4;function nt({runId:e,event:t}){let[n,r]=(0,B.useState)(null),[a,o]=(0,B.useState)(`agent`),[c,l]=(0,B.useState)(!1),u=t.note?.code;if((0,B.useEffect)(()=>{u===`personDrives`?o(`person`):u===`agentDrives`&&o(`agent`)},[u]),(0,B.useEffect)(()=>{let t=()=>_.get(`/api/runs/${e}/browser/seat`).then(e=>o(e.seat)).catch(()=>void 0);if(t(),a!==`person`)return;let n=setInterval(t,tt);return()=>clearInterval(n)},[e,a]),n!==null&&n>=t.id)return null;let d=a===`person`,f=async()=>{l(!0);try{let t=await _.post(`/api/runs/${e}/browser/seat`,{to:d?`agent`:`person`});o(t.seat)}catch{}finally{l(!1)}};return(0,V.jsx)(s,{runId:e,driving:d,caption:i(t),hint:w(`browser.driving`),onBroken:()=>r(t.id),className:`mt-1.5`,action:(0,V.jsxs)(`button`,{type:`button`,disabled:c,onClick:()=>void f(),className:m(`flex h-8 items-center gap-1.5 rounded-full px-3 font-medium text-[0.8125rem] shadow-soft transition-colors disabled:opacity-60`,d?`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:[d?(0,V.jsx)(ve,{className:`size-3.5`}):(0,V.jsx)(ge,{className:`size-3.5`}),w(d?`browser.handBack`:`browser.takeOver`)]})},n??0)}function $({children:e,end:t}){return(0,V.jsxs)(`div`,{className:`mb-3 flex flex-wrap items-center justify-between gap-2`,children:[(0,V.jsx)(`h3`,{className:`font-display font-semibold text-[1rem]`,children:e}),t]})}function rt({view:e,run:t,step:n,before:r,asked:i,onNote:a}){let o=e.shown.filter(e=>e.output),[s,l]=(0,B.useState)(o.length===1?o[0].step.id:null),u=(0,B.useRef)(null),d=[...r,...i.map((e,t)=>W(`review:${n.id}:asked:${t}`,e)),U(`review:${n.id}`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`span`,{className:`font-medium`,children:n.title}),n.description?(0,V.jsx)(`span`,{className:`mt-0.5 block text-ink-2`,children:n.description}):null]}),{anchor:!0}),...o.map(({step:t,output:r})=>U(`review:${n.id}:${t.id}`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)($,{children:t.title}),(0,V.jsx)(I,{base:`/api/runs/${e.id}`,step:t,output:r,onSurfaceAction:n.regenerate?()=>{l(t.id),u.current?.focus()}:void 0})]}),{wide:!0})),...e.lists.map(t=>U(`review:${n.id}:list:${t.def.id}`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)($,{children:t.def.title}),t.def.check?(0,V.jsx)(C,{runId:e.id,list:t}):(0,V.jsx)(ie,{runId:e.id,list:t,editable:!0})]}),{wide:!0}))];t.error&&d.push(U(`review-error`,t.error,{tone:`error`}));let f=n.regenerate&&o.length>0;return d.push(X(`review:${n.id}:replies`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsxs)(Z,{primary:!0,busy:t.busy,onClick:()=>void t.accept(n.id),children:[(0,V.jsx)(c,{className:`size-4`}),` `,w(`run.accept`)]}),f&&o.length>1?o.map(({step:e})=>(0,V.jsx)(Z,{on:s===e.id,onClick:()=>l(e.id),children:e.title},e.id)):null]}))),(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(J,{avatar:e.wizard.avatar,lines:d}),f?(0,V.jsx)(K,{children:(0,V.jsx)(Le,{multiline:!0,inputRef:u,busy:t.busy,placeholder:o.length>1&&!s?w(`run.feedbackPick`):w(`run.feedbackPlaceholder`),disabled:!s,onSend:e=>{let r=e.trim();return!r||!s?!1:(a(r),t.regenerate(n.id,s,r),!0)}})}):(0,V.jsx)(Q,{})]})}function it({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,U(`result:${n.id}`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`span`,{className:`font-display font-semibold text-[1.0625rem]`,children:n.title}),n.message?(0,V.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})=>U(`result:${e.id}`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)($,{end:(0,V.jsx)(P,{base:o,stepId:e.id,formats:n,title:r??e.title}),children:r??e.title}),(0,V.jsx)(I,{base:o,step:e,output:t}),t?.assets?.some(e=>e.ai)?(0,V.jsx)(`p`,{className:`mt-3 text-[0.75rem] text-ink-3 leading-relaxed`,children:w(`ai.publish`)}):null]}),{wide:!0})),...e.lists.map(t=>U(`result:list:${t.def.id}`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)($,{end:(0,V.jsx)(ne,{runId:e.id,list:t}),children:t.label??t.def.title}),(0,V.jsx)(ie,{runId:e.id,list:t,editable:!0})]}),{wide:!0}))];return s.push(X(`result:replies`,(0,V.jsxs)(V.Fragment,{children:[a.length?(0,V.jsx)(fe,{runId:e.id,title:`${n.title} · ${e.wizard.title}`,initial:e.shareUrl?{url:e.shareUrl,expiresAt:e.expiresAt}:null}):null,i?(0,V.jsxs)(Z,{onClick:i,children:[(0,V.jsx)(R,{className:`size-4`}),` `,w(`run.again`)]}):null,e.canBack?(0,V.jsx)(Z,{onClick:()=>void t.back(),disabled:t.busy,children:w(`run.back`)}):null,e.keeps?(0,V.jsx)(`span`,{className:`ml-1`,children:(0,V.jsx)(E,{runId:e.id})}):null]}))),(0,V.jsx)(J,{avatar:e.wizard.avatar,lines:s})}function at({runId:e,onRestart:t,onView:n,header:r,footer:i,talk:a=!1,call:o=!1}){let s=me(e),{view:c}=s,[u,d]=(0,B.useState)(null),f=Ne(e,c,s,u);(0,B.useEffect)(()=>{n?.(c)},[c,n]);let[p,m]=le(),g=(0,B.useMemo)(()=>({runId:e,lang:c?.lang??A,readAloud:p,setReadAloud:m,voice:c?.talk?f:null,talk:a,call:!!o,bindPage:d}),[e,c?.lang,c?.talk,p,m,f,a,o]);h(c?.status===`running`&&!c.ask),k(c);let[_,v]=(0,B.useState)({}),[b,x]=(0,B.useState)(null);(0,B.useEffect)(()=>{c&&c.status!==`running`&&x(null)},[c]);let S;if(s.notFound)S=(0,V.jsx)(`div`,{className:`py-24 text-center text-ink-3`,children:w(`run.notFound`)});else if(!c)S=(0,V.jsx)(`div`,{className:`flex justify-center py-24 text-ink-4`,children:(0,V.jsx)(L,{})});else{let e=c.step,n=c.status===`waiting_input`,r=qe(c,c.canBack&&n&&!s.busy?()=>void s.back():void 0);if(c.status===`running`&&c.ask)S=(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,U(`ask:${c.ask.id}`,(0,V.jsx)(l,{runId:c.id,ask:c.ask}),{wide:!0})]}),(0,V.jsx)(Q,{})]});else if(c.status===`running`)S=(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,...b?[W(`note`,b)]:[],U(`working:${e?.id}`,(0,V.jsx)(Qe,{view:c}),{wide:c.events.some(t=>t.stepId===e?.id&&et(t))?`most`:void 0})]}),(0,V.jsx)(Q,{placeholder:w(`run.working`)})]});else if(c.status===`failed`)S=(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,U(`failed`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`span`,{className:`font-medium`,children:w(`run.failed`)}),c.error?(0,V.jsx)(`span`,{className:`mt-0.5 block`,children:(0,V.jsx)(y,{text:c.error})}):null]}),{tone:`error`}),X(`failed:replies`,(0,V.jsxs)(V.Fragment,{children:[(0,V.jsxs)(Z,{primary:!0,busy:s.busy,onClick:()=>void s.retry(),children:[(0,V.jsx)(R,{className:`size-4`}),` `,w(`run.retry`)]}),c.canBack?(0,V.jsx)(Z,{onClick:()=>void s.back(),disabled:s.busy,children:w(`run.back`)}):null]}))]}),(0,V.jsx)(Q,{})]});else if(c.status===`cancelled`)S=(0,V.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,U(`cancelled`,w(`run.cancelled`)),...t?[X(`cancelled:replies`,(0,V.jsxs)(Z,{primary:!0,onClick:t,children:[(0,V.jsx)(R,{className:`size-4`}),` `,w(`run.again`)]}))]:[]]});else if(e?.type===`page`)S=(0,V.jsx)(Ye,{view:c,run:s,step:e,before:r},e.id);else if(e?.type===`review`){let t=c.shown.map(e=>e.output?.at??``).join(`|`);S=(0,V.jsx)(rt,{view:c,run:s,step:e,before:r,asked:_[e.id]??[],onNote:t=>{x(t),v(n=>({...n,[e.id]:[...n[e.id]??[],t]}))}},`${e.id}:${t}`)}else S=e?.type===`result`?(0,V.jsx)(it,{view:c,run:s,step:e,before:r,onRestart:t}):(0,V.jsx)(J,{avatar:c.wizard.avatar,lines:r})}return o?(0,V.jsx)(G.Provider,{value:g,children:(0,V.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col lg:flex-row`,children:[(0,V.jsx)(De,{voice:f,view:c,video:o===`video`,className:`h-[46dvh] shrink-0 lg:h-auto lg:min-h-0 lg:flex-1`}),(0,V.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,V.jsx)(q,{footer:i,children:S})})]})}):(0,V.jsx)(G.Provider,{value:g,children:(0,V.jsx)(q,{header:r,footer:i,children:S})})}export{J as a,Z as i,q as n,X as o,Q as r,Fe as s,at as t};
|