wizards 0.4.3 → 0.4.5

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.
Files changed (129) hide show
  1. package/apps/runtime/dist/agents/architect.js +32 -13
  2. package/apps/runtime/dist/agents/subscription.js +12 -12
  3. package/apps/runtime/dist/app.js +9 -5
  4. package/apps/runtime/dist/assistant/knows.js +2 -2
  5. package/apps/runtime/dist/authoring/example.js +21 -20
  6. package/apps/runtime/dist/authoring/guide.js +4 -2
  7. package/apps/runtime/dist/connectors/imap.js +4 -4
  8. package/apps/runtime/dist/connectors/index.js +40 -15
  9. package/apps/runtime/dist/connectors/plugin-connections.js +3 -2
  10. package/apps/runtime/dist/connectors/via-account.js +8 -6
  11. package/apps/runtime/dist/docs/dev/plugins/connections.md +1 -1
  12. package/apps/runtime/dist/docs/dev/plugins/reference.md +5 -1
  13. package/apps/runtime/dist/docs/dev/plugins/routes.md +35 -1
  14. package/apps/runtime/dist/docs/dev/plugins/server.md +27 -1
  15. package/apps/runtime/dist/docs/dev/plugins/starters.md +1 -1
  16. package/apps/runtime/dist/documents/parse.js +5 -3
  17. package/apps/runtime/dist/engine/events.js +1 -1
  18. package/apps/runtime/dist/engine/input.js +28 -8
  19. package/apps/runtime/dist/engine/prepare.js +2 -2
  20. package/apps/runtime/dist/engine/requirements.js +12 -3
  21. package/apps/runtime/dist/engine/runner.js +34 -23
  22. package/apps/runtime/dist/engine/steps.js +6 -5
  23. package/apps/runtime/dist/engine/surface.js +2 -1
  24. package/apps/runtime/dist/engine/template.js +1 -1
  25. package/apps/runtime/dist/engine/types.js +2 -1
  26. package/apps/runtime/dist/film/project.js +1 -1
  27. package/apps/runtime/dist/film/skills.js +2 -2
  28. package/apps/runtime/dist/film/sounds.js +1 -1
  29. package/apps/runtime/dist/film/step.js +7 -4
  30. package/apps/runtime/dist/film/tools.js +1 -1
  31. package/apps/runtime/dist/geocode.js +1 -1
  32. package/apps/runtime/dist/harness/apple.js +0 -5
  33. package/apps/runtime/dist/harness/claude.js +2 -1
  34. package/apps/runtime/dist/harness/codex.js +2 -1
  35. package/apps/runtime/dist/harness/model.js +4 -3
  36. package/apps/runtime/dist/harness/terminal.js +4 -3
  37. package/apps/runtime/dist/manage.js +29 -0
  38. package/apps/runtime/dist/model-errors.js +8 -3
  39. package/apps/runtime/dist/models.js +58 -38
  40. package/apps/runtime/dist/plugins/channels.js +77 -0
  41. package/apps/runtime/dist/plugins/loader.js +9 -1
  42. package/apps/runtime/dist/plugins/public.js +16 -2
  43. package/apps/runtime/dist/plugins/registry.js +1 -0
  44. package/apps/runtime/dist/plugins/runs.js +2 -1
  45. package/apps/runtime/dist/routes/api.js +16 -5
  46. package/apps/runtime/dist/routes/lang.js +13 -0
  47. package/apps/runtime/dist/routes/plugin-public.js +65 -12
  48. package/apps/runtime/dist/routes/runs.js +12 -19
  49. package/apps/runtime/dist/routes/studio.js +40 -28
  50. package/apps/runtime/dist/services/access.js +4 -3
  51. package/apps/runtime/dist/services/architect.js +15 -4
  52. package/apps/runtime/dist/services/assistant-chats.js +2 -1
  53. package/apps/runtime/dist/services/brand.js +3 -2
  54. package/apps/runtime/dist/services/errors.js +7 -5
  55. package/apps/runtime/dist/services/knowledge-model.js +3 -2
  56. package/apps/runtime/dist/services/marketplace.js +6 -5
  57. package/apps/runtime/dist/services/package.js +10 -3
  58. package/apps/runtime/dist/services/profile.js +12 -0
  59. package/apps/runtime/dist/services/project-files.js +13 -12
  60. package/apps/runtime/dist/services/projects.js +11 -6
  61. package/apps/runtime/dist/services/runs.js +18 -11
  62. package/apps/runtime/dist/services/shares.js +2 -1
  63. package/apps/runtime/dist/services/site.js +21 -10
  64. package/apps/runtime/dist/services/space-categories.js +7 -6
  65. package/apps/runtime/dist/services/space-data.js +19 -16
  66. package/apps/runtime/dist/services/spaces.js +8 -7
  67. package/apps/runtime/dist/services/wizards.js +41 -20
  68. package/apps/runtime/dist/store/errors.js +2 -1
  69. package/apps/runtime/dist/store/index.js +21 -4
  70. package/apps/runtime/dist/store/shared-lists.js +2 -3
  71. package/apps/runtime/dist/tools/index.js +17 -2
  72. package/apps/runtime/dist/tools/plugin.js +3 -2
  73. package/apps/runtime/dist/widgets/render.js +1 -1
  74. package/apps/runtime/dist/widgets/step.js +2 -1
  75. package/apps/web/dist/assets/{AboutDialog-DWaBKvI6.js → AboutDialog-BCtnYRj2.js} +1 -1
  76. package/apps/web/dist/assets/{ChangelogDialog-BcM1gXPM.js → ChangelogDialog-DBjoIIHL.js} +1 -1
  77. package/apps/web/dist/assets/ChatView-BcyUYN0Q.js +10 -0
  78. package/apps/web/dist/assets/EditorPage-Ce1QD-DK.js +3 -0
  79. package/apps/web/dist/assets/{FlowPreview-S1s1yRaP.js → FlowPreview-BtpAdyt-.js} +1 -1
  80. package/apps/web/dist/assets/{Harness-DILx5Edb.js → Harness-DJJ_yMLY.js} +2 -2
  81. package/apps/web/dist/assets/NewWizardChannels-BrYLMV6F.js +1 -0
  82. package/apps/web/dist/assets/NewWizardPage-827zwhhW.js +7 -0
  83. package/apps/web/dist/assets/{OnboardingPage-xoGrKIJ-.js → OnboardingPage-jC6FidpF.js} +1 -1
  84. package/apps/web/dist/assets/ProjectPage-BYcM1-1H.js +1 -0
  85. package/apps/web/dist/assets/{PublicRunner-Cab2jUy6.js → PublicRunner-BofZl0MO.js} +1 -1
  86. package/apps/web/dist/assets/{ReadOnly-DQPHmvS0.js → ReadOnly-B4nIGkoj.js} +1 -1
  87. package/apps/web/dist/assets/RunDrawer-Dx-BRCkY.js +4 -0
  88. package/apps/web/dist/assets/RunnerView-CDCp61aq.js +1 -0
  89. package/apps/web/dist/assets/SettingsPage-B49nLHwv.js +1 -0
  90. package/apps/web/dist/assets/SetupPage-4tzzHUq0.js +1 -0
  91. package/apps/web/dist/assets/SharePage-Bs4s73h4.js +1 -0
  92. package/apps/web/dist/assets/changelog-D-12LwZB.js +1 -0
  93. package/apps/web/dist/assets/{circle-alert-DCBV7n5k.js → circle-alert-BueS7qO8.js} +1 -1
  94. package/apps/web/dist/assets/esm-CjGdsKU4.js +7 -0
  95. package/apps/web/dist/assets/index-BRDn-5v_.js +14 -0
  96. package/apps/web/dist/assets/index-mlnAPOdf.css +1 -0
  97. package/apps/web/dist/assets/{lock-DlzTfwxP.js → lock-CkXYnQux.js} +1 -1
  98. package/apps/web/dist/assets/{phone-BFD815nc.js → phone-CHkEf-Dz.js} +1 -1
  99. package/apps/web/dist/assets/settings-menu-CrVpArM_.js +1 -0
  100. package/apps/web/dist/assets/ui-DrdqFaQt.js +134 -0
  101. package/apps/web/dist/assets/{upload-BEf5-d6X.js → upload-CzkkZqAo.js} +1 -1
  102. package/apps/web/dist/index.html +4 -4
  103. package/apps/web/dist/mcp/flow.html +76 -76
  104. package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +98 -2
  105. package/node_modules/@engenty-wizards/plugin-sdk/dist/thread.js +6 -1
  106. package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +6 -2
  107. package/node_modules/@engenty-wizards/shared/dist/definition.js +13 -5
  108. package/node_modules/@engenty-wizards/shared/dist/knowledge.js +1 -1
  109. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +11 -1
  110. package/node_modules/@engenty-wizards/shared/dist/run.js +11 -1
  111. package/node_modules/@engenty-wizards/shared/dist/store.d.ts +8 -0
  112. package/node_modules/@engenty-wizards/shared/dist/store.js +8 -0
  113. package/package.json +1 -1
  114. package/apps/web/dist/assets/ChatView-D0RRIl15.js +0 -10
  115. package/apps/web/dist/assets/EditorPage-DrJ6e_2q.js +0 -3
  116. package/apps/web/dist/assets/NewWizardChannels-CEILDADp.js +0 -1
  117. package/apps/web/dist/assets/NewWizardPage-DxOtK2E-.js +0 -7
  118. package/apps/web/dist/assets/ProjectPage-6E5z4nZA.js +0 -1
  119. package/apps/web/dist/assets/RunDrawer-B3FNYpgZ.js +0 -4
  120. package/apps/web/dist/assets/RunnerView-D6sGVnRy.js +0 -1
  121. package/apps/web/dist/assets/SettingsPage-DHtIqmOJ.js +0 -1
  122. package/apps/web/dist/assets/SetupPage-Cn9iQbJx.js +0 -1
  123. package/apps/web/dist/assets/SharePage-CMr72PeU.js +0 -1
  124. package/apps/web/dist/assets/changelog-DfmWTlav.js +0 -1
  125. package/apps/web/dist/assets/esm-BPfTI3lL.js +0 -7
  126. package/apps/web/dist/assets/index-B-D8UvL9.js +0 -14
  127. package/apps/web/dist/assets/index-CmxVazOf.css +0 -1
  128. package/apps/web/dist/assets/settings-menu-BJm0CwOj.js +0 -1
  129. package/apps/web/dist/assets/ui-DTuixH4y.js +0 -134
@@ -537,6 +537,60 @@ export interface PluginPublicRoute {
537
537
  path: string;
538
538
  handler(request: PluginPublicRequest): unknown | Promise<unknown>;
539
539
  }
540
+ /** What a shared route's handler gets: nobody is signed in, and no tenant yet. */
541
+ export interface PluginSharedRequest {
542
+ request: Request;
543
+ /** The address below the plugin's shared one. */
544
+ path: string;
545
+ params: Record<string, string>;
546
+ query: URLSearchParams;
547
+ /**
548
+ * Runs `work` inside the tenant whose public address has this ref (`server.publicRef()`),
549
+ * when the tenant is active and has the plugin. Throws with the status `404` and the code
550
+ * `not_found` otherwise.
551
+ */
552
+ inTenant<T>(ref: string, work: () => T | Promise<T>): Promise<T>;
553
+ }
554
+ /**
555
+ * A route for every tenant at once, at the address `sharedUrl` gives: for a service that posts
556
+ * to one webhook for all of them (one account of the runtime's, one app). The call names its
557
+ * tenant only by what it carries – the ref of the tenant's address, handed to the service
558
+ * before (`publicRef`) – so check the service's signature first, then `inTenant`.
559
+ */
560
+ export interface PluginSharedRoute {
561
+ method: PluginHttpMethod;
562
+ path: string;
563
+ handler(request: PluginSharedRequest): unknown | Promise<unknown>;
564
+ }
565
+ /** A kind of use of a number of the Manage-App's. */
566
+ export type PluginChannelKind = "sms" | "call" | "whatsapp";
567
+ /**
568
+ * The numbers a Manage-App gives the tenant (docs/manage-contract.md): its own number for
569
+ * texts and calls, asked for and assigned there, and the numbers every tenant shares.
570
+ */
571
+ export interface PluginChannels {
572
+ number: {
573
+ /** With the country code: `+43…`. */
574
+ number: string;
575
+ /** ISO 3166, upper case: `AT`. */
576
+ country: string;
577
+ kinds: PluginChannelKind[];
578
+ /** The provider's id of the number (Twilio's `PN…`); null when none was entered. */
579
+ providerRef: string | null;
580
+ } | null;
581
+ /** The tenant's open request for its number; null for none. */
582
+ request: {
583
+ id: string;
584
+ country: string;
585
+ wish: string | null;
586
+ createdAt: string;
587
+ } | null;
588
+ shared: {
589
+ number: string;
590
+ country: string;
591
+ kinds: PluginChannelKind[];
592
+ }[];
593
+ }
540
594
  /** An account a plugin connected for a space: a calendar, a mailbox. */
541
595
  export interface PluginConnection {
542
596
  id: string;
@@ -579,12 +633,14 @@ export interface PluginConnections {
579
633
  * The provider's sign-in page of an `oauth2` connector. Open it in a window: when the person
580
634
  * is done, the window posts `{ type: "wizards:connected", ok }` to the studio and closes.
581
635
  * `actions` are the connector's actions the plugin will call; only the rights they need are
582
- * asked for.
636
+ * asked for. `lang` is the language the person reads; the page they come back to speaks it,
637
+ * else their browser's.
583
638
  */
584
639
  start(input: {
585
640
  space: string;
586
641
  connector: string;
587
642
  actions: string[];
643
+ lang?: "de" | "en";
588
644
  }): Promise<{
589
645
  url: string;
590
646
  }>;
@@ -623,7 +679,7 @@ export interface PluginStarter {
623
679
  title: string;
624
680
  /** What it makes, in one or two sentences. */
625
681
  description: string;
626
- /** The language its texts are in. Default: German. */
682
+ /** The language its texts are in. Default: English. */
627
683
  language?: "de" | "en";
628
684
  /** A complete wizard definition. Checked when it is registered. */
629
685
  definition: unknown;
@@ -939,6 +995,46 @@ export interface PluginServerApi {
939
995
  registerPublicRoute(route: PluginPublicRoute): void;
940
996
  /** The full address of a public route for the current tenant: what to hand to whoever calls it. */
941
997
  publicUrl(path: string): Promise<string>;
998
+ /** The part of `publicUrl` that names the current tenant: what a shared route's call carries. */
999
+ publicRef(): Promise<string>;
1000
+ /** A route for every tenant at once (one webhook of a service for all of them). */
1001
+ registerSharedRoute(route: PluginSharedRoute): void;
1002
+ /** The full address of a shared route, the same for every tenant. */
1003
+ sharedUrl(path: string): string;
1004
+ /**
1005
+ * The numbers the Manage-App gives the current tenant. `get` is null on a runtime without a
1006
+ * Manage-App; there `request` and `withdraw` throw, and `book` books nothing.
1007
+ */
1008
+ channels: {
1009
+ /** Kept for a minute. */
1010
+ get(): Promise<PluginChannels | null>;
1011
+ /**
1012
+ * A person of the tenant asks for its number. Throws with the status `403` and the code
1013
+ * `plan` on a plan without one, `409` and `has_number` when the tenant has it; asking again
1014
+ * answers the open request.
1015
+ */
1016
+ request(input: {
1017
+ userId: string;
1018
+ /** ISO 3166: `AT`. */
1019
+ country: string;
1020
+ wish?: string | null;
1021
+ lang: "de" | "en";
1022
+ }): Promise<NonNullable<PluginChannels["request"]>>;
1023
+ /** Takes the open request back; false when there was none. */
1024
+ withdraw(): Promise<boolean>;
1025
+ /**
1026
+ * Books what the tenant's number carried, at the Manage-App's prices: `sms` by segment
1027
+ * (sent or received), `call` by started minute. The same `key` twice books once.
1028
+ */
1029
+ book(input: {
1030
+ kind: "sms" | "call";
1031
+ quantity: number;
1032
+ key: string;
1033
+ runId?: string | null;
1034
+ }): Promise<{
1035
+ credits: number;
1036
+ }>;
1037
+ };
942
1038
  /**
943
1039
  * Runs `handler` for every tenant that has the plugin, at most once per `everyMs` (a minute
944
1040
  * at least), inside that tenant. When it ran is kept: a restart does not start the count again,
@@ -1,4 +1,4 @@
1
- export const freshThreadState = (lang = "de") => ({
1
+ export const freshThreadState = (lang = "en") => ({
2
2
  lang,
3
3
  wizardId: null,
4
4
  page: null,
@@ -260,6 +260,11 @@ export class ThreadDoor {
260
260
  await this.send(thread, { kind: "text", text: say(thread.state.lang, "stopped") });
261
261
  }
262
262
  async menu(thread, offered) {
263
+ // Before a wizard is picked, the thread speaks the wizards' language where they share one.
264
+ const spoken = new Set(offered.map((w) => w.lang));
265
+ if (spoken.size === 1) {
266
+ thread.state.lang = offered[0].lang;
267
+ }
263
268
  const lang = thread.state.lang;
264
269
  if (!offered.length) {
265
270
  await this.send(thread, { kind: "text", text: say(lang, "nothing") });
@@ -1767,6 +1767,10 @@ export declare const wizardSchema: z.ZodObject<{
1767
1767
  wedge: "wedge";
1768
1768
  }>>;
1769
1769
  intro: z.ZodOptional<z.ZodString>;
1770
+ lang: z.ZodOptional<z.ZodEnum<{
1771
+ en: "en";
1772
+ de: "de";
1773
+ }>>;
1770
1774
  lists: z.ZodOptional<z.ZodArray<z.ZodObject<{
1771
1775
  id: z.ZodString;
1772
1776
  title: z.ZodString;
@@ -2680,8 +2684,8 @@ export interface ItemsTotals {
2680
2684
  export declare function itemsTotals(field: Field, value: unknown, values: Record<string, unknown>): ItemsTotals;
2681
2685
  export declare function allFields(def: WizardDefinition): Field[];
2682
2686
  /**
2683
- * The language a wizard speaks to people, read from its own words (titles, labels, intro).
2684
- * A definition carries none; German where it is not clearly English.
2687
+ * The language a wizard speaks to people: the one it names, else read from its own words
2688
+ * (titles, labels, intro) — English where they are not clearly German.
2685
2689
  */
2686
2690
  export declare function wizardLang(def: WizardDefinition): "de" | "en";
2687
2691
  /** The locale amounts and dates are written in for a wizard's language. */
@@ -580,6 +580,11 @@ export const wizardSchema = z.object({
580
580
  avatar: z.enum(ENGENTY_KINDS).default("round"),
581
581
  /** Shown on the first page above the first question. */
582
582
  intro: z.string().optional(),
583
+ /**
584
+ * The language the wizard speaks to people: its texts, the runner's words, its numbers and
585
+ * dates. Without one it is read from the wizard's own words (`wizardLang`).
586
+ */
587
+ lang: z.enum(["de", "en"]).optional(),
583
588
  /** Tabular data the wizard keeps between runs, per person — or for all runs (`shared`). */
584
589
  lists: z.array(listSchema).max(12).optional(),
585
590
  /** Accounts the person connects; kept between runs, per person. */
@@ -1523,7 +1528,7 @@ export function slotTime(iso) {
1523
1528
  return { day: `${m[1]}-${m[2]}-${m[3]}`, time: `${m[4]}:${m[5]}`, wall };
1524
1529
  }
1525
1530
  /** The weekday and date of a slot's day: "Montag, 12. Oktober" / "Monday, 12 October". */
1526
- export function slotDayText(iso, lang = "de") {
1531
+ export function slotDayText(iso, lang = "en") {
1527
1532
  const slot = slotTime(iso);
1528
1533
  if (!slot) {
1529
1534
  return iso;
@@ -1538,7 +1543,7 @@ export function slotDayText(iso, lang = "de") {
1538
1543
  return `${weekday}, ${date}`;
1539
1544
  }
1540
1545
  /** A chosen slot as a person reads it back: "Di 13.10.2026, 10:30" / "Tue 13/10/2026, 10:30". */
1541
- export function slotText(iso, lang = "de") {
1546
+ export function slotText(iso, lang = "en") {
1542
1547
  const slot = slotTime(iso);
1543
1548
  if (!slot) {
1544
1549
  return iso;
@@ -1606,10 +1611,13 @@ export function allFields(def) {
1606
1611
  const GERMAN = /\b(und|der|die|das|ist|nicht|für|mit|ein|eine|wird|zu|dein|deine|ihr|wir|was|wie|oder)\b|[äöüß]/gi;
1607
1612
  const ENGLISH = /\b(and|the|is|not|for|with|a|an|your|you|we|what|how|or|to|of)\b/gi;
1608
1613
  /**
1609
- * The language a wizard speaks to people, read from its own words (titles, labels, intro).
1610
- * A definition carries none; German where it is not clearly English.
1614
+ * The language a wizard speaks to people: the one it names, else read from its own words
1615
+ * (titles, labels, intro) — English where they are not clearly German.
1611
1616
  */
1612
1617
  export function wizardLang(def) {
1618
+ if (def.lang) {
1619
+ return def.lang;
1620
+ }
1613
1621
  const text = [
1614
1622
  def.title,
1615
1623
  def.description,
@@ -1624,7 +1632,7 @@ export function wizardLang(def) {
1624
1632
  .join(" ");
1625
1633
  const de = text.match(GERMAN)?.length ?? 0;
1626
1634
  const en = text.match(ENGLISH)?.length ?? 0;
1627
- return en > de ? "en" : "de";
1635
+ return de > en ? "de" : "en";
1628
1636
  }
1629
1637
  /** The locale amounts and dates are written in for a wizard's language. */
1630
1638
  export const LOCALES = { de: "de-DE", en: "en-GB" };
@@ -64,5 +64,5 @@ export function slugOf(title) {
64
64
  .replace(/[^a-z0-9]+/g, "-")
65
65
  .replace(/^-+|-+$/g, "")
66
66
  .slice(0, 60)
67
- .replace(/-+$/, "") || "seite");
67
+ .replace(/-+$/, "") || "page");
68
68
  }
@@ -153,12 +153,16 @@ export interface ShownList {
153
153
  label: string | null;
154
154
  }
155
155
  /**
156
- * What a step reports while it works, in words for each language: the runtime writes the German
156
+ * What a step reports while it works, in words for each language: the runtime writes the English
157
157
  * line into the run's log, a runner shows it in the language the person reads. The runtime's
158
158
  * answers to the person running a shared wizard (a refusal, a failure) are notes too: it answers
159
159
  * them in the wizard's language.
160
160
  */
161
161
  export declare const RUN_NOTES: {
162
+ readonly text: {
163
+ readonly de: "{de}";
164
+ readonly en: "{en}";
165
+ };
162
166
  readonly entry: {
163
167
  readonly de: "Eintrag {n} von {total}";
164
168
  readonly en: "Entry {n} of {total}";
@@ -522,6 +526,12 @@ export interface RunNote {
522
526
  code: RunNoteCode;
523
527
  params?: Record<string, string | number>;
524
528
  }
529
+ /** What the person reads: plain words, or a note that has a line for each language. */
530
+ export type Said = string | RunNote;
531
+ /** What is said, in a language. */
532
+ export declare function saidText(said: Said, lang: "de" | "en"): string;
533
+ /** Free text in both languages, carried as a note: a runner or a response picks the line. */
534
+ export declare function bilingual(de: string, en: string): RunNote;
525
535
  /** A note in a language, its gaps filled. */
526
536
  export declare function noteText(note: RunNote, lang: "de" | "en"): string;
527
537
  export interface RunEvent {
@@ -1,10 +1,12 @@
1
1
  /**
2
- * What a step reports while it works, in words for each language: the runtime writes the German
2
+ * What a step reports while it works, in words for each language: the runtime writes the English
3
3
  * line into the run's log, a runner shows it in the language the person reads. The runtime's
4
4
  * answers to the person running a shared wizard (a refusal, a failure) are notes too: it answers
5
5
  * them in the wizard's language.
6
6
  */
7
7
  export const RUN_NOTES = {
8
+ // A line written out in both languages where no line of its own fits (`bilingual`).
9
+ text: { de: "{de}", en: "{en}" },
8
10
  entry: { de: "Eintrag {n} von {total}", en: "Entry {n} of {total}" },
9
11
  deciding: { de: "Entscheidet, wie es weitergeht …", en: "Deciding how to go on …" },
10
12
  choosingFields: { de: "Wählt die passenden Fragen …", en: "Choosing the right questions …" },
@@ -238,6 +240,14 @@ export const RUN_NOTES = {
238
240
  en: "Apple Intelligence: the recording could not be converted: {detail}",
239
241
  },
240
242
  };
243
+ /** What is said, in a language. */
244
+ export function saidText(said, lang) {
245
+ return typeof said === "string" ? said : noteText(said, lang);
246
+ }
247
+ /** Free text in both languages, carried as a note: a runner or a response picks the line. */
248
+ export function bilingual(de, en) {
249
+ return { code: "text", params: { de, en } };
250
+ }
241
251
  /** A note in a language, its gaps filled. */
242
252
  export function noteText(note, lang) {
243
253
  const line = RUN_NOTES[note.code];
@@ -94,6 +94,14 @@ export interface ConnectionView {
94
94
  }
95
95
  /** One list as a Markdown table of raw cell values — what a model reads. */
96
96
  export declare function listAsMarkdown(def: ListDef, rows: ListRow[], limit?: number): string;
97
+ /**
98
+ * When the first row saved now is stamped, in milliseconds: after every row the list already
99
+ * holds, so a list reads in the order its rows came — also when two saves fall in one
100
+ * millisecond. The rows of one save follow it a millisecond apart.
101
+ */
102
+ export declare function firstRowAt(existing: {
103
+ createdAt: Date;
104
+ }[]): number;
97
105
  /** The key a row is matched on: trimmed and lower-cased, so "Notion " and "notion" are one row. */
98
106
  export declare function rowKey(def: ListDef, cells: Record<string, unknown>): string | null;
99
107
  /** A new row's cells, typed by the list's columns. Throws `TableColumnValueError` on a bad value. */
@@ -24,6 +24,14 @@ export function listAsMarkdown(def, rows, limit = 200) {
24
24
  const more = rows.length > limit ? [`… ${rows.length - limit} more rows`] : [];
25
25
  return [head, ...body, ...more].join("\n");
26
26
  }
27
+ /**
28
+ * When the first row saved now is stamped, in milliseconds: after every row the list already
29
+ * holds, so a list reads in the order its rows came — also when two saves fall in one
30
+ * millisecond. The rows of one save follow it a millisecond apart.
31
+ */
32
+ export function firstRowAt(existing) {
33
+ return existing.reduce((at, row) => Math.max(at, row.createdAt.getTime() + 1), Date.now());
34
+ }
27
35
  /** The key a row is matched on: trimmed and lower-cased, so "Notion " and "notion" are one row. */
28
36
  export function rowKey(def, cells) {
29
37
  if (!def.key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wizards",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
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,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{At as r,Bn as i,Cn as a,Ft as o,J as s,Mt as c,Nt as l,Pt as u,Q as d,Rn as f,Wn as p,Wt as m,X as h,Xt as g,Z as _,an as v,at as y,c as b,cn as x,ct as S,dn as C,en as w,fn as T,ht as E,it as D,lt as O,mn as k,nn as A,nt as j,ot as M,qt as N,rn as P,st as F,tn as I,un as ee,vn as te,wt as L,xn as ne,z as R}from"./ui-DTuixH4y.js";import{t as re}from"./phone-BFD815nc.js";import{J as ie,Ot as ae,X as oe,Y as se,dt as ce,jt as le,qt as ue,t as de,vt as fe}from"./index-B-D8UvL9.js";import{n as pe}from"./RunnerView-D6sGVnRy.js";var me={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`}]]};me.node;var he=p(me),ge={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`}]]};ge.node;var _e=p(ge),ve={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`}]]};ve.node;var ye=p(ve),be={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`}]]};be.node;var xe=p(be),Se=ue(),z=e(t(),1),B=e(n(),1),Ce=typeof window<`u`&&window.matchMedia(`(pointer: coarse)`).matches;function we({since:e}){let[t,n]=(0,z.useState)(Date.now());if((0,z.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,B.jsxs)(`span`,{className:`font-mono text-[0.8125rem] text-white/60 tabular-nums`,children:[i,`:`,a]})}function V({label:e,on:t,danger:n,busy:r,onClick:i,children:a}){return(0,B.jsx)(`button`,{type:`button`,"aria-label":e,title:e,"aria-pressed":t,disabled:r,onClick:i,className:I(`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,B.jsx)(g,{className:`size-5`}):a})}function Te({voice:e}){let t=(0,z.useRef)(null),{captions:n}=e;return(0,z.useEffect)(()=>{n.length&&t.current?.scrollIntoView({block:`end`})},[n]),n.length?(0,B.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 sm:px-5`,children:(0,B.jsxs)(`ol`,{className:`mx-auto flex max-w-[720px] flex-col gap-2 py-2`,children:[n.map(e=>(0,B.jsx)(`li`,{className:I(`text-[0.9375rem] leading-snug`,e.who===`bot`?`text-white/95`:`text-right text-white/50`),children:e.text},e.id)),(0,B.jsx)(`div`,{ref:t})]})}):null}function Ee({voice:e,view:t,video:n,className:r}){let i=e.state===`live`,o=e.state===`connecting`,[s,c]=(0,z.useState)(null),[l,u]=(0,z.useState)(!1);(0,z.useEffect)(()=>{c(i?Date.now():null)},[i]);let d=async()=>{u(!1),await e.start(),n&&await e.startCamera()},f=()=>{e.stop(),u(!0)},p=n||e.camera,m=[...e.captions].reverse().find(e=>e.who===`bot`),h=[...e.captions].reverse().find(e=>e.who===`me`),_=e.speaking?v(`talk.speaking`):e.listening?v(`talk.listening`):i?v(`talk.live`):o?v(`talk.connecting`):l?v(`video.ended`):``;return(0,B.jsxs)(`section`,{className:I(`relative flex min-h-0 flex-col bg-neutral-950 text-white`,`safe-top`,r),children:[(0,B.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 px-4 sm:px-5`,children:[(0,B.jsx)(`div`,{className:`min-w-0 flex-1 truncate font-display font-semibold text-[1rem] tracking-tight`,children:t?.wizard.title??``}),_?(0,B.jsxs)(`span`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-white/70`,children:[i?(0,B.jsx)(`span`,{className:I(`size-2 rounded-full`,e.speaking?`animate-pulse-dot bg-emerald-400`:`bg-rose`)}):null,_]}):null,(0,B.jsx)(we,{since:s})]}),(0,B.jsxs)(`div`,{className:I(`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,B.jsxs)(`div`,{className:I(`relative min-h-0 overflow-hidden rounded-2xl bg-neutral-900`,!p&&`hidden`),children:[(0,B.jsx)(`video`,{ref:e.video,muted:!0,playsInline:!0,autoPlay:!0,className:I(`absolute inset-0 h-full w-full object-cover`,e.facing===`user`&&`-scale-x-100`,e.camera?`block`:`hidden`)}),e.camera?null:(0,B.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/50`,children:[(0,B.jsx)(ye,{className:`size-8`}),(0,B.jsx)(`span`,{className:`text-[0.8125rem]`,children:v(`video.cameraOff`)})]}),(0,B.jsxs)(`span`,{className:`absolute bottom-2 left-3 rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:[v(`video.you`),e.muted?(0,B.jsx)(le,{className:`ml-1.5 inline size-3`}):null]})]}),(0,B.jsxs)(`div`,{className:I(`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,B.jsx)(`div`,{className:I(`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,B.jsx)(ce,{kind:t?.wizard.avatar??`round`,size:p?140:200,fluffy:!0,interactive:!1})}),p?(0,B.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,B.jsx)(Te,{voice:e}):i&&(m||h)?(0,B.jsx)(`div`,{className:`shrink-0 px-4 pb-2 sm:px-5`,children:(0,B.jsxs)(`div`,{className:`mx-auto max-w-[720px] space-y-1 text-center`,children:[h?(0,B.jsx)(`p`,{className:`line-clamp-1 text-[0.8125rem] text-white/50`,children:h.text}):null,m?(0,B.jsx)(`p`,{className:`line-clamp-3 text-[0.9375rem] text-white/95 leading-snug`,children:m.text}):null]})}):null,e.error?(0,B.jsx)(`p`,{className:`shrink-0 px-5 pb-2 text-center text-[0.8125rem] text-rose`,children:e.error}):null,(0,B.jsx)(`div`,{className:`flex shrink-0 items-center justify-center gap-3 px-4 pt-1 pb-4`,children:i?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(V,{label:v(e.muted?`video.unmute`:`video.mute`),on:!e.muted,onClick:e.toggleMute,children:e.muted?(0,B.jsx)(le,{className:`size-5`}):(0,B.jsx)(a,{className:`size-5`})}),(0,B.jsx)(V,{label:v(e.camera?`talk.cameraOff`:`talk.camera`),on:e.camera,onClick:()=>e.camera?e.stopCamera():void e.startCamera(),children:e.camera?(0,B.jsx)(x,{className:`size-5`}):(0,B.jsx)(ye,{className:`size-5`})}),e.camera&&Ce?(0,B.jsx)(V,{label:v(`video.flip`),onClick:()=>void e.flipCamera(),children:(0,B.jsx)(ee,{className:`size-5`})}):null,(0,B.jsx)(V,{label:v(`video.leave`),danger:!0,onClick:f,children:(0,B.jsx)(ae,{className:`size-5`})})]}):(0,B.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[(0,B.jsxs)(`button`,{type:`button`,disabled:o||!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:[o?(0,B.jsx)(g,{className:`size-4`}):n?(0,B.jsx)(x,{className:`size-5`}):(0,B.jsx)(a,{className:`size-5`}),v(l?`video.rejoin`:n?`video.join`:`talk.start`)]}),!l&&!e.error?(0,B.jsx)(`p`,{className:`max-w-sm text-center text-[0.75rem] text-white/50`,children:v(n?`video.hint`:`talk.joinHint`)}):null]})})]})}var De=e=>E[e.kind]!==`device`,Oe=1024,ke=4e3;function H(e,t){return e?e.length>t?`${e.slice(0,t)} …`:e:``}function U(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: ${A(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}: ${H(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=De(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?` = ${H(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}": ${H(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,z.useState)(`off`),[o,s]=(0,z.useState)(null),[c,l]=(0,z.useState)(!1),[u,d]=(0,z.useState)(!1),[f,p]=(0,z.useState)(!1),[m,h]=(0,z.useState)(`environment`),[g,_]=(0,z.useState)(!1),[y,b]=(0,z.useState)([]),x=(0,z.useRef)(null),S=(0,z.useRef)(null),C=(0,z.useRef)(0),w=(0,z.useRef)(!1);w.current=f;let T=(0,z.useRef)(null),E=(0,z.useRef)(null),D=(0,z.useRef)(null),O=(0,z.useRef)(null),k=(0,z.useRef)(t);k.current=t;let A=(0,z.useRef)(r);A.current=r;let j=(0,z.useRef)(n);j.current=n;let M=(0,z.useRef)(``),N=(0,z.useCallback)(e=>{let t=E.current;t&&t.readyState===`open`&&t.send(JSON.stringify(e))},[]),P=(0,z.useCallback)(()=>{let e=x.current;if(!w.current||!e||e.videoWidth===0)return null;let t=Math.min(1,Oe/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,z.useCallback)(()=>{for(let e of S.current?.getTracks()??[])e.stop();S.current=null,x.current&&(x.current.srcObject=null),p(!1)},[]),I=(0,z.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`?v(`talk.cameraDenied`):e.message)}},[]),ee=(0,z.useCallback)(async()=>{let e=m===`user`?`environment`:`user`;F(),await I(e)},[m,F,I]),te=(0,z.useCallback)(()=>{_(e=>{for(let t of O.current?.getAudioTracks()??[])t.enabled=e;return!e})},[]),L=(0,z.useCallback)(()=>{F(),E.current?.close(),E.current=null,T.current?.close(),T.current=null;for(let e of O.current?.getTracks()??[])e.stop();O.current=null,D.current&&=(D.current.srcObject=null,D.current.remove(),null),M.current=``,l(!1),d(!1),_(!1),a(`off`)},[F]);(0,z.useEffect)(()=>()=>L(),[L]);let ne=(0,z.useCallback)(async(t,n)=>{let r=k.current,i=A.current,a=j.current;switch(t){case`get_state`:return r?U(r,i,w.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 R.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&&De(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 R.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]),re=(0,z.useCallback)(async()=>{if(!T.current){s(null),b([]),a(`connecting`);try{let t=await R.post(`/api/runs/${e}/talk`),n=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}});O.current=n;let r=new RTCPeerConnection;T.current=r;let i=document.createElement(`audio`);i.autoplay=!0,i.setAttribute(`playsinline`,``),document.body.append(i),D.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`);E.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>ke?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{}ne(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=k.current;e&&(M.current=U(e,A.current,w.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=()=>{T.current===r&&L()};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(`${v(`talk.failed`)} (${u.status})`);await r.setRemoteDescription({type:`answer`,sdp:await u.text()})}catch(e){L(),s(e.name===`NotAllowedError`?v(`chat.micDenied`):e.message),a(`error`)}}},[e,ne,P,N,L]);return(0,z.useEffect)(()=>{if(i!==`live`||!t)return;let e=U(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:re,stop:L,camera:f,facing:m,startCamera:I,stopCamera:F,flipCamera:ee,muted:g,toggleMute:te,captions:y,video:x}}var W=(e,t,n)=>({key:e,who:`bot`,node:t,...n}),G=(e,t,n)=>({key:e,who:`me`,node:t,...n}),je=(0,z.createContext)(null),K=(0,z.createContext)(null);function Me(){return(0,z.useContext)(K)?.voice??null}function q({children:e}){let t=(0,z.useContext)(je);return t?(0,Se.createPortal)(e,t):null}function Ne({header:e,footer:t,children:n}){let[r,i]=(0,z.useState)(null),a=(0,z.useRef)(null),o=(0,z.useRef)(null),s=(0,z.useRef)(!0);return(0,z.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,B.jsx)(je.Provider,{value:r,children:(0,B.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[e,(0,B.jsx)(`div`,{ref:a,className:`min-h-0 flex-1 overflow-y-auto overscroll-contain`,children:(0,B.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,B.jsxs)(`div`,{className:`shrink-0 border-border-soft border-t bg-background`,onPointerDownCapture:()=>{s.current=!0},onKeyDownCapture:()=>{s.current=!0},children:[(0,B.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,z.useContext)(K),r=(0,z.useMemo)(()=>t.map(e=>({key:e.key,who:e.who,spoken:!e.bare&&!e.wide})),[t]),i=(0,z.useCallback)(e=>{let t=document.querySelector(`[data-say="${CSS.escape(e)}"]`);return t?.querySelector(`[data-say-text]`)?.getAttribute(`data-say-text`)??t?.innerText??null},[]);oe(!!n?.readAloud,n?.lang??P,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,B.jsxs)(`div`,{className:`flex items-start gap-2.5`,children:[(0,B.jsx)(`div`,{className:`sticky top-1 shrink-0 pt-0.5`,children:(0,B.jsx)(ce,{kind:e,size:30,interactive:n>=a.length-2})}),(0,B.jsx)(`div`,{className:`flex min-w-0 flex-1 flex-col items-start gap-1.5`,children:t.lines.map(e=>(0,B.jsx)(`div`,{"data-anchor":e.anchor?``:void 0,"data-say":e.key,className:I(`animate-rise`,e.bare?`w-full pt-1`:`rounded-2xl rounded-tl-md text-[0.9375rem] text-ink leading-relaxed`,!e.bare&&(e.wide?I(`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,B.jsxs)(`div`,{className:`flex animate-rise flex-col items-end gap-1 pl-10`,children:[(0,B.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,B.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,B.jsx)(te,{className:`size-3`}),` `,v(`chat.change`)]}):null]},e.key)))}function Pe(){return(0,B.jsx)(`span`,{className:`inline-flex items-center gap-1 py-1.5`,role:`status`,"aria-label":v(`run.working`),children:[0,1,2].map(e=>(0,B.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,B.jsx)(`div`,{className:`flex flex-wrap items-center gap-2`,children:e})}var X=(e,t)=>W(e,(0,B.jsx)(Y,{children:t}),{bare:!0});function Z({onClick:e,children:t,primary:n,on:r,disabled:i,busy:a}){return(0,B.jsxs)(`button`,{type:`button`,"aria-pressed":r,disabled:i||a,onClick:e,className:I(`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,B.jsx)(g,{className:`size-4`}):null,t]})}function Fe({initial:e=``,placeholder:t,multiline:n,inputProps:r,busy:o,disabled:s,inputRef:l,onSend:u}){let[d,f]=(0,z.useState)(e),p=(0,z.useRef)(null),h=l??p,_=(0,z.useContext)(K),y=b(d,f,{endpoint:_?`/api/runs/${_.runId}/transcribe`:void 0}),S=!!_&&y.supported&&!s;(0,z.useEffect)(()=>{if(!S)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)},[S,y.toggle]),(0,z.useEffect)(()=>{!c&&!s&&h.current?.focus()},[s,h]);let T=()=>{o||s||(y.listening&&y.toggle(),u(d)!==!1&&f(``))},E=y.listening?v(`chat.listening`):y.processing?v(`chat.transcribing`):t,D=_?.voice??null,O=!!_?.call,k=_&&!O&&(ie||S||D)?(0,B.jsxs)(`div`,{className:`mb-1 flex shrink-0 items-center`,children:[D?(0,B.jsx)(m,{label:v(D.state===`live`?`talk.stop`:D.state===`connecting`?`talk.connecting`:`talk.start`),"aria-pressed":D.state===`live`,disabled:D.state===`connecting`,onClick:()=>D.state===`live`?D.stop():void D.start(),className:I(`size-9`,D.state===`live`&&`bg-rose-tint text-rose hover:bg-rose-tint hover:text-rose`,D.state===`off`&&_.talk&&`bg-primary text-primary-foreground hover:bg-primary`),children:D.state===`connecting`?(0,B.jsx)(g,{className:`size-4`}):D.state===`live`?(0,B.jsx)(ae,{className:`size-4`}):(0,B.jsx)(re,{className:`size-4`})}):null,D?.state===`live`?(0,B.jsx)(m,{label:v(D.camera?`talk.cameraOff`:`talk.camera`),"aria-pressed":D.camera,onClick:()=>D.camera?D.stopCamera():void D.startCamera(),className:I(`size-9`,D.camera&&`text-ink`),children:D.camera?(0,B.jsx)(x,{className:`size-4`}):(0,B.jsx)(ye,{className:`size-4`})}):null,ie?(0,B.jsx)(m,{label:v(_.readAloud?`chat.readAloudOff`:`chat.readAloud`),"aria-pressed":_.readAloud,onClick:()=>_.setReadAloud(!_.readAloud),className:I(`size-9`,_.readAloud&&`text-ink`),children:_.readAloud?(0,B.jsx)(fe,{className:`size-4`}):(0,B.jsx)(xe,{className:`size-4`})}):null,S?(0,B.jsx)(m,{label:v(y.listening?`chat.dictateStop`:`chat.dictate`),"aria-pressed":y.listening,disabled:y.processing,onClick:y.toggle,className:I(`size-9`,y.listening&&`bg-rose-tint text-rose hover:bg-rose-tint hover:text-rose`),children:y.processing?(0,B.jsx)(g,{className:`size-4`}):y.listening?(0,B.jsx)(C,{className:`size-3.5 animate-pulse-dot fill-current`}):(0,B.jsx)(a,{className:`size-4`})}):null]}):null;return(0,B.jsxs)(`form`,{className:`pb-3`,onSubmit:e=>{e.preventDefault(),T()},children:[D&&!O?(0,B.jsx)(`video`,{ref:D.video,muted:!0,playsInline:!0,autoPlay:!0,className:I(`mb-2 ml-auto w-32 rounded-xl bg-black object-cover shadow-soft ring-1 ring-border-soft`,D.camera?`block`:`hidden`)}):null,(0,B.jsxs)(`div`,{className:I(`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`,s&&`opacity-60`),children:[k,n?(0,B.jsx)(w,{ref:h,minRows:1,maxRows:6,value:d,disabled:s,placeholder:E,autoCapitalize:`sentences`,onChange:e=>f(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!c&&!e.nativeEvent.isComposing&&(e.preventDefault(),T())},className:`min-h-11 border-0 bg-transparent py-2.5 shadow-none focus:ring-0`}):(0,B.jsx)(`input`,{ref:h,...r,value:d,disabled:s,placeholder:E,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,B.jsx)(`button`,{type:`submit`,"aria-label":v(`chat.send`),title:v(`chat.send`),disabled:o||s,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:o?(0,B.jsx)(g,{className:`size-4`}):(0,B.jsx)(i,{className:`size-4`})})]}),y.error?(0,B.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-rose`,children:y.error===`denied`?v(`chat.micDenied`):y.error}):O?null:D?.error?(0,B.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-rose`,children:D.error}):D?.state===`live`?(0,B.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-ink-3`,children:D.speaking?v(`talk.speaking`):D.listening?v(`talk.listening`):v(`talk.live`)}):_?.talk&&D?.state===`off`?(0,B.jsx)(`p`,{className:`mt-1.5 px-3 text-[0.75rem] text-ink-3`,children:v(`talk.hint`)}):null]})}function Q({placeholder:e=v(`chat.above`)}){return(0,B.jsx)(q,{children:(0,B.jsx)(Fe,{disabled:!0,placeholder:e,onSend:()=>!1})})}function Ie(e){let t=E[e.kind];return t===`typed`&&!e.scan?`typed`:t===`tapped`?`tapped`:`control`}var Le=e=>e==null||e===``||Array.isArray(e)&&e.length===0;function Re(e,t){let n=e.kind===`toggle`||e.kind===`connection`||e.kind===`list`;if(Le(t))return e.required&&!n?v(`chat.required`):null;let r=String(t).trim();if(e.kind===`email`&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r))return v(`chat.badEmail`);if(e.kind===`url`)try{new URL(r)}catch{return v(`chat.badUrl`)}return e.kind===`number`&&!Number.isFinite(Number(r.replace(`,`,`.`)))?v(`chat.badNumber`):Array.isArray(t)&&e.multiple&&e.min&&t.length<e.min?v(`run.filesMin`,{n:t.length,min:e.min}):null}function ze(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 Be({field:e}){return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`span`,{className:`font-medium`,children:e.label}),e.help?(0,B.jsx)(`span`,{className:`mt-0.5 block text-[0.8125rem] text-ink-3`,children:e.help}):null]})}function Ve({step:e,only:t}){return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`span`,{className:`font-medium`,children:e.title}),e.description?(0,B.jsx)(`span`,{className:`mt-0.5 block text-ink-2`,children:e.description}):null,t?.help?(0,B.jsx)(`span`,{className:`mt-1 block text-[0.8125rem] text-ink-3`,children:t.help}):null]})}function He({field:e,value:t,runId:n}){if(e.kind===`connection`)return(0,B.jsx)(B.Fragment,{children:typeof t==`string`&&t?t:v(`chat.connected`)});if(e.kind===`list`)return(0,B.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,B.jsx)(f,{className:`size-4`}),` `,v(`chat.checked`)]});if(e.kind===`toggle`)return(0,B.jsx)(B.Fragment,{children:v(t===!0?`run.yes`:`run.no`)});if(Le(t))return(0,B.jsx)(`span`,{className:`italic opacity-80`,children:v(`chat.skipped`)});switch(e.kind){case`multiselect`:return(0,B.jsx)(B.Fragment,{children:t.join(`, `)});case`date`:{let e=new Date(`${String(t)}T00:00`);return(0,B.jsx)(B.Fragment,{children:Number.isNaN(e.getTime())?String(t):new Intl.DateTimeFormat(P,{dateStyle:`long`}).format(e)})}case`color`:return(0,B.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[(0,B.jsx)(`span`,{className:`size-4 rounded-full ring-1 ring-white/50`,style:{background:String(t)}}),String(t)]});case`image`:case`signature`:return(0,B.jsx)(`span`,{className:`-mx-1.5 flex flex-wrap gap-1.5`,children:(Array.isArray(t)?t:[String(t)]).map(t=>(0,B.jsx)(`img`,{src:s(`/api/runs/${n}/assets/${t}`),alt:``,className:I(`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,B.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,B.jsx)(ne,{className:`size-4`}),` `,v(e===1?`chat.file`:`chat.files`,{n:e})]})}case`audio`:{let e=t.seconds;return(0,B.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,B.jsx)(a,{className:`size-4`}),` `,v(`chat.voice`),e?` · ${Math.round(e)} s`:``]})}case`location`:{let e=t;return(0,B.jsx)(B.Fragment,{children:e.label||`${e.lat?.toFixed(5)}, ${e.lng?.toFixed(5)}`})}case`items`:return(0,B.jsx)(B.Fragment,{children:v(`chat.rows`,{n:Array.isArray(t)?t.length:0})});default:return(0,B.jsx)(B.Fragment,{children:String(t)})}}function Ue(e,t,n,r,i,a){let o=[W(t,(0,B.jsx)(Ve,{step:e,only:a}))];for(let e of i)a||o.push(W(`${t}:${e.id}`,(0,B.jsx)(Be,{field:e}))),o.push(G(`${t}:${e.id}:a`,(0,B.jsx)(He,{field:e,value:n[e.id],runId:r})));return o}var We=(e,t)=>e.fields.filter(e=>!e.when&&!L(e)||t[e.id]!==void 0&&t[e.id]!==null);function Ge(e,t){let n=[];e.wizard.description&&n.push(W(`hello`,e.wizard.description)),e.wizard.intro&&n.push(W(`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(...Ue(r,i,e.values,e.id,We(r,e.values),t))}else r.type===`review`&&(n.push(W(i,(0,B.jsx)(`span`,{className:`font-medium`,children:r.title}))),n.push(G(`${i}:a`,v(`run.accept`))))}let r=n.at(-1);return t&&r?.who===`me`&&(n[n.length-1]={...r,onEdit:t}),n}function Ke(e,t){return e.fields.filter(e=>!L(e)||t.decidedFields?.includes(e.id)).map(e=>t.options?.[e.id]?.length?{...e,options:t.options[e.id]}:e)}function qe({view:e,run:t,step:n,before:i}){let a=(0,z.useMemo)(()=>Ke(n,e),[n,e]),o=e.known??{},[s,c]=(0,z.useState)(()=>h(n,e)),[l,u]=(0,z.useState)(()=>n.fields.some(t=>e.values[t.id]!==void 0)?r(Ke(n,e),e.known??{},h(n,e)).slice(0,-1).map(e=>e.id):[]),[d,f]=(0,z.useState)({}),[p,m]=(0,z.useState)(!1),[g,_]=(0,z.useState)(!1),y=r(a,o,s),b=y.filter(e=>l.includes(e.id)),x=y.find(e=>!l.includes(e.id)),S=a.length===1?a[0]:void 0,C=b.at(-1),w=C?()=>u(e=>e.filter(e=>e!==C.id)):void 0;(0,z.useEffect)(()=>{let e=Object.keys(t.fieldErrors),n=r(a,o,s),i=n.findIndex(t=>e.includes(t.id));i>=0&&(u(n.slice(0,i).map(e=>e.id)),f(t.fieldErrors))},[t.fieldErrors]);let T=e=>{t.submitPage(n.id,e).then(_)},E=(0,z.useContext)(K),O=(0,z.useRef)(s);O.current=s;let k=E?.bindPage,A=(0,z.useRef)(T);A.current=T,(0,z.useEffect)(()=>{if(!k)return;let e=r(a,o,s);return k({step:n,fields:e,values:s,setField:(t,n)=>{let r=e.find(e=>e.id===t);return r?Re(r,n)||(c(e=>({...e,[t]:n})),u(e=>e.includes(t)?e:[...e,t]),f({}),null):`no such field on this page`},submit:()=>A.current(O.current)}),()=>k(null)},[k,n,a,o,s]);let j=e=>{if(!x)return!1;let t=Re(x,e);if(t)return f({[x.id]:t}),!1;let n={...s,[x.id]:e},i=[...l,x.id];return c(n),u(i),f({}),r(a,o,n).some(e=>!i.includes(e.id))||T(n),!0},M=[...i.map(e=>l.length?{...e,onEdit:void 0}:e),...Ue(n,`now:${n.id}`,s,e.id,b,S).map((e,t,n)=>t===n.length-1&&e.who===`me`&&x?{...e,onEdit:w}:e)];x?(Ie(x)===`control`?M.push(W(`now:${n.id}:${x.id}:control`,(0,B.jsx)(D,{field:x,value:s[x.id],values:s,runId:e.id,view:e,closed:e.closed?.[x.id],onChange:e=>c(t=>({...t,[x.id]:e})),onBusy:m}),{wide:!0})):S||M.push(W(`now:${n.id}:${x.id}`,(0,B.jsx)(Be,{field:x}))),d[x.id]&&M.push(W(`now:${n.id}:${x.id}:error`,d[x.id],{tone:`error`}))):t.busy||g?M.push(W(`sending`,(0,B.jsx)(Pe,{}))):t.error&&M.push(W(`send-error`,t.error,{tone:`error`}));let N=(0,B.jsx)(Q,{});if(g||!x&&l.length>0&&t.busy)N=(0,B.jsx)(Q,{placeholder:v(`run.working`)});else if(!x)M.push(X(`now:${n.id}:go`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(Z,{primary:!0,busy:t.busy,onClick:()=>T(s),children:n.cta||v(`run.next`)}),w?(0,B.jsx)(Z,{onClick:w,disabled:t.busy,children:v(`run.back`)}):null]})));else{let r=Ie(x),i=!x.required&&x.kind!==`connection`&&x.kind!==`list`?(0,B.jsx)(Z,{onClick:()=>j(void 0),children:v(`chat.skip`)}):null;if(r===`typed`){i&&M.push(X(`now:${n.id}:${x.id}:replies`,i));let e=s[x.id];N=(0,B.jsx)(q,{children:(0,B.jsx)(Fe,{initial:Le(e)?``:String(e),multiline:x.kind===`textarea`,placeholder:x.placeholder||(S?x.label:v(`chat.placeholder`)),inputProps:Je(x),busy:t.busy,onSend:e=>j(ze(x,e))},x.id)})}else if(r===`tapped`)M.push(W(`now:${n.id}:${x.id}:replies`,(0,B.jsx)(Ye,{field:x,view:e,value:s[x.id],onAnswer:j}),{bare:!0}));else{let e=y.filter(e=>!l.includes(e.id)).length===1;M.push(X(`now:${n.id}:${x.id}:replies`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(Z,{primary:!0,disabled:p,onClick:()=>j(s[x.id]),children:e&&n.cta?n.cta:v(`chat.send`)}),i]})))}}return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(J,{avatar:e.wizard.avatar,lines:M}),N]})}function Je(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 y(e)}}function Ye({field:e,view:t,value:n,onAnswer:r}){let i=new Set(t.closed?.[e.id]?.values.map(String)),[a,o]=(0,z.useState)(Array.isArray(n)?n:[]);if(e.kind===`toggle`)return(0,B.jsxs)(Y,{children:[(0,B.jsx)(Z,{on:n===!1,disabled:i.has(`false`),onClick:()=>r(!1),children:v(`run.no`)}),(0,B.jsx)(Z,{on:n===!0,disabled:i.has(`true`),onClick:()=>r(!0),children:v(`run.yes`)})]});let s=e.options??[];return e.kind===`multiselect`?(0,B.jsxs)(Y,{children:[s.map(e=>(0,B.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:e},e)),(0,B.jsx)(Z,{primary:!0,disabled:e.required&&!a.length,onClick:()=>r(a),children:a.length||e.required?v(`chat.send`):v(`chat.skip`)})]}):(0,B.jsxs)(Y,{children:[s.map(e=>(0,B.jsx)(Z,{on:n===e,disabled:i.has(e),onClick:()=>r(e),children:e},e)),e.required?null:(0,B.jsx)(Z,{onClick:()=>r(void 0),children:v(`chat.skip`)})]})}function Xe({view:e}){let t=(0,z.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(),[r,i]=(0,z.useState)(Date.now());(0,z.useEffect)(()=>{let e=setInterval(()=>i(Date.now()),1e3);return()=>clearInterval(e)},[]);let a=e.events.filter(e=>(e.type===`tool`||e.type===`info`)&&new Date(e.at).getTime()>=n-500),o=a.at(-1),c=[...a].reverse().find(Qe),l=[...new Set(a.map(e=>e.asset).filter(e=>!!e))];return(0,B.jsxs)(`div`,{className:I(`flex max-w-full flex-col gap-1`,c?`w-full`:`w-96`),"data-say-text":t?.message??e.step?.title??v(`run.working`),children:[(0,B.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,B.jsx)(Pe,{}),(0,B.jsx)(`span`,{className:`font-medium`,children:t?.message??e.step?.title??v(`run.working`)}),(0,B.jsx)(`span`,{className:`text-[0.75rem] text-ink-4 tabular-nums`,children:v(`run.elapsed`,{s:Math.max(0,Math.round((r-n)/1e3))})})]}),o&&o!==c?(0,B.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-ink-3`,children:[(0,B.jsx)(T,{className:`size-3.5 shrink-0 animate-breathe text-ember`}),(0,B.jsx)(`span`,{className:`truncate`,children:A(o)})]}):null,c&&e.status===`running`?(0,B.jsx)(et,{runId:e.id,event:c}):null,l.length?(0,B.jsx)(`div`,{className:`mt-1.5 flex flex-wrap gap-1.5`,children:l.slice(-6).map(t=>(0,B.jsx)(`img`,{src:s(`/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 Ze=new Set([`opens`,`clicks`,`clicksOn`,`types`,`typesText`,`selects`,`scrolls`,`presses`,`goesBack`,`waitsForPage`,`fastLoop`,`looksAtPage`,`personDrives`,`agentDrives`]);function Qe(e){return!!e.note&&Ze.has(e.note.code)}var $e=1e4;function et({runId:e,event:t}){let[n,r]=(0,z.useState)(null),[i,a]=(0,z.useState)(`agent`),[s,c]=(0,z.useState)(!1),l=t.note?.code;if((0,z.useEffect)(()=>{l===`personDrives`?a(`person`):l===`agentDrives`&&a(`agent`)},[l]),(0,z.useEffect)(()=>{let t=()=>R.get(`/api/runs/${e}/browser/seat`).then(e=>a(e.seat)).catch(()=>void 0);if(t(),i!==`person`)return;let n=setInterval(t,$e);return()=>clearInterval(n)},[e,i]),n!==null&&n>=t.id)return null;let u=i===`person`,d=async()=>{c(!0);try{let t=await R.post(`/api/runs/${e}/browser/seat`,{to:u?`agent`:`person`});a(t.seat)}catch{}finally{c(!1)}};return(0,B.jsx)(o,{runId:e,driving:u,caption:A(t),hint:v(`browser.driving`),onBroken:()=>r(t.id),className:`mt-1.5`,action:(0,B.jsxs)(`button`,{type:`button`,disabled:s,onClick:()=>void d(),className:I(`flex h-8 items-center gap-1.5 rounded-full px-3 font-medium text-[0.8125rem] shadow-soft transition-colors disabled:opacity-60`,u?`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:[u?(0,B.jsx)(_e,{className:`size-3.5`}):(0,B.jsx)(he,{className:`size-3.5`}),v(u?`browser.handBack`:`browser.takeOver`)]})},n??0)}function $({children:e,end:t}){return(0,B.jsxs)(`div`,{className:`mb-3 flex flex-wrap items-center justify-between gap-2`,children:[(0,B.jsx)(`h3`,{className:`font-display font-semibold text-[1rem]`,children:e}),t]})}function tt({view:e,run:t,step:n,before:r,asked:i,onNote:a}){let o=e.shown.filter(e=>e.output),[s,c]=(0,z.useState)(o.length===1?o[0].step.id:null),l=(0,z.useRef)(null),u=[...r,...i.map((e,t)=>G(`review:${n.id}:asked:${t}`,e)),W(`review:${n.id}`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`span`,{className:`font-medium`,children:n.title}),n.description?(0,B.jsx)(`span`,{className:`mt-0.5 block text-ink-2`,children:n.description}):null]}),{anchor:!0}),...o.map(({step:t,output:r})=>W(`review:${n.id}:${t.id}`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)($,{children:t.title}),(0,B.jsx)(j,{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=>W(`review:${n.id}:list:${t.def.id}`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)($,{children:t.def.title}),t.def.check?(0,B.jsx)(M,{runId:e.id,list:t}):(0,B.jsx)(S,{runId:e.id,list:t,editable:!0})]}),{wide:!0}))];t.error&&u.push(W(`review-error`,t.error,{tone:`error`}));let d=n.regenerate&&o.length>0;return u.push(X(`review:${n.id}:replies`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(Z,{primary:!0,busy:t.busy,onClick:()=>void t.accept(n.id),children:[(0,B.jsx)(f,{className:`size-4`}),` `,v(`run.accept`)]}),d&&o.length>1?o.map(({step:e})=>(0,B.jsx)(Z,{on:s===e.id,onClick:()=>c(e.id),children:e.title},e.id)):null]}))),(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(J,{avatar:e.wizard.avatar,lines:u}),d?(0,B.jsx)(q,{children:(0,B.jsx)(Fe,{multiline:!0,inputRef:l,busy:t.busy,placeholder:o.length>1&&!s?v(`run.feedbackPick`):v(`run.feedbackPlaceholder`),disabled:!s,onSend:e=>{let r=e.trim();return!r||!s?!1:(a(r),t.regenerate(n.id,s,r),!0)}})}):(0,B.jsx)(Q,{})]})}function nt({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,W(`result:${n.id}`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`span`,{className:`font-display font-semibold text-[1.0625rem]`,children:n.title}),n.message?(0,B.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})=>W(`result:${e.id}`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)($,{end:(0,B.jsx)(d,{base:o,stepId:e.id,formats:n,title:r??e.title}),children:r??e.title}),(0,B.jsx)(j,{base:o,step:e,output:t}),t?.assets?.some(e=>e.ai)?(0,B.jsx)(`p`,{className:`mt-3 text-[0.75rem] text-ink-3 leading-relaxed`,children:v(`ai.publish`)}):null]}),{wide:!0})),...e.lists.map(t=>W(`result:list:${t.def.id}`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)($,{end:(0,B.jsx)(F,{runId:e.id,list:t}),children:t.label??t.def.title}),(0,B.jsx)(S,{runId:e.id,list:t,editable:!0})]}),{wide:!0}))];return s.push(X(`result:replies`,(0,B.jsxs)(B.Fragment,{children:[a.length?(0,B.jsx)(de,{runId:e.id,title:`${n.title} · ${e.wizard.title}`,initial:e.shareUrl?{url:e.shareUrl,expiresAt:e.expiresAt}:null}):null,i?(0,B.jsxs)(Z,{onClick:i,children:[(0,B.jsx)(k,{className:`size-4`}),` `,v(`run.again`)]}):null,e.canBack?(0,B.jsx)(Z,{onClick:()=>void t.back(),disabled:t.busy,children:v(`run.back`)}):null,e.keeps?(0,B.jsx)(`span`,{className:`ml-1`,children:(0,B.jsx)(O,{runId:e.id})}):null]}))),(0,B.jsx)(J,{avatar:e.wizard.avatar,lines:s})}function rt({runId:e,onRestart:t,onView:n,header:r,footer:i,talk:a=!1,call:o=!1}){let s=pe(e),{view:c}=s,[d,f]=(0,z.useState)(null),p=Ae(e,c,s,d);(0,z.useEffect)(()=>{n?.(c)},[c,n]);let[m,h]=se(),y=(0,z.useMemo)(()=>({runId:e,lang:c?.lang??P,readAloud:m,setReadAloud:h,voice:c?.talk?p:null,talk:a,call:!!o,bindPage:f}),[e,c?.lang,c?.talk,m,h,p,a,o]);l(c?.status===`running`&&!c.ask),_(c);let[b,x]=(0,z.useState)({}),[S,C]=(0,z.useState)(null);(0,z.useEffect)(()=>{c&&c.status!==`running`&&C(null)},[c]);let w;if(s.notFound)w=(0,B.jsx)(`div`,{className:`py-24 text-center text-ink-3`,children:v(`run.notFound`)});else if(!c)w=(0,B.jsx)(`div`,{className:`flex justify-center py-24 text-ink-4`,children:(0,B.jsx)(g,{})});else{let e=c.step,n=c.status===`waiting_input`,r=Ge(c,c.canBack&&n&&!s.busy?()=>void s.back():void 0);if(c.status===`running`&&c.ask)w=(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,W(`ask:${c.ask.id}`,(0,B.jsx)(u,{runId:c.id,ask:c.ask}),{wide:!0})]}),(0,B.jsx)(Q,{})]});else if(c.status===`running`)w=(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,...S?[G(`note`,S)]:[],W(`working:${e?.id}`,(0,B.jsx)(Xe,{view:c}),{wide:c.events.some(t=>t.stepId===e?.id&&Qe(t))?`most`:void 0})]}),(0,B.jsx)(Q,{placeholder:v(`run.working`)})]});else if(c.status===`failed`)w=(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,W(`failed`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`span`,{className:`font-medium`,children:v(`run.failed`)}),c.error?(0,B.jsx)(`span`,{className:`mt-0.5 block`,children:(0,B.jsx)(N,{text:c.error})}):null]}),{tone:`error`}),X(`failed:replies`,(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(Z,{primary:!0,busy:s.busy,onClick:()=>void s.retry(),children:[(0,B.jsx)(k,{className:`size-4`}),` `,v(`run.retry`)]}),c.canBack?(0,B.jsx)(Z,{onClick:()=>void s.back(),disabled:s.busy,children:v(`run.back`)}):null]}))]}),(0,B.jsx)(Q,{})]});else if(c.status===`cancelled`)w=(0,B.jsx)(J,{avatar:c.wizard.avatar,lines:[...r,W(`cancelled`,v(`run.cancelled`)),...t?[X(`cancelled:replies`,(0,B.jsxs)(Z,{primary:!0,onClick:t,children:[(0,B.jsx)(k,{className:`size-4`}),` `,v(`run.again`)]}))]:[]]});else if(e?.type===`page`)w=(0,B.jsx)(qe,{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(`|`);w=(0,B.jsx)(tt,{view:c,run:s,step:e,before:r,asked:b[e.id]??[],onNote:t=>{C(t),x(n=>({...n,[e.id]:[...n[e.id]??[],t]}))}},`${e.id}:${t}`)}else w=e?.type===`result`?(0,B.jsx)(nt,{view:c,run:s,step:e,before:r,onRestart:t}):(0,B.jsx)(J,{avatar:c.wizard.avatar,lines:r})}return o?(0,B.jsx)(K.Provider,{value:y,children:(0,B.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col lg:flex-row`,children:[(0,B.jsx)(Ee,{voice:p,view:c,video:o===`video`,className:`h-[46dvh] shrink-0 lg:h-auto lg:min-h-0 lg:flex-1`}),(0,B.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,B.jsx)(Ne,{footer:i,children:w})})]})}):(0,B.jsx)(K.Provider,{value:y,children:(0,B.jsx)(Ne,{header:r,footer:i,children:w})})}export{J as a,Z as i,Ne as n,X as o,Q as r,Me as s,rt as t};