wizards 0.3.8 → 0.4.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.
Files changed (59) hide show
  1. package/README.md +28 -14
  2. package/apps/runtime/dist/auth/account.js +36 -4
  3. package/apps/runtime/dist/auth/device.js +101 -0
  4. package/apps/runtime/dist/auth/index.js +4 -4
  5. package/apps/runtime/dist/cli/account.js +289 -0
  6. package/apps/runtime/dist/cli/install-env.js +33 -0
  7. package/apps/runtime/dist/cli/main.js +17 -3
  8. package/apps/runtime/dist/cli/menu.js +19 -5
  9. package/apps/runtime/dist/cli/setup.js +9 -16
  10. package/apps/runtime/dist/cli/status.js +4 -1
  11. package/apps/runtime/dist/cli/ui.js +14 -0
  12. package/apps/runtime/dist/docs/user/command-line.md +3 -2
  13. package/apps/runtime/dist/docs/user/create-account.md +47 -0
  14. package/apps/runtime/dist/docs/user/first-start.md +9 -1
  15. package/apps/runtime/dist/docs/user/index.md +16 -12
  16. package/apps/runtime/dist/docs/user/install.md +3 -1
  17. package/apps/runtime/dist/docs/user/local-only.md +38 -0
  18. package/apps/runtime/dist/docs/user/meta.json +3 -1
  19. package/apps/runtime/dist/docs/user/models.md +3 -2
  20. package/apps/runtime/dist/manage.js +12 -0
  21. package/apps/runtime/dist/plugins/pro.js +16 -16
  22. package/apps/runtime/dist/routes/studio.js +41 -2
  23. package/apps/runtime/dist/services/cloud.js +10 -10
  24. package/apps/runtime/dist/services/onboarding.js +152 -0
  25. package/apps/web/dist/assets/{AboutDialog-ClV4gNiW.js → AboutDialog-CPQiN7H9.js} +1 -1
  26. package/apps/web/dist/assets/{ChangelogDialog-DsSEkayM.js → ChangelogDialog-DynvQuuR.js} +1 -1
  27. package/apps/web/dist/assets/{ChatView-BdYCnDLk.js → ChatView-CKo_9IZD.js} +1 -1
  28. package/apps/web/dist/assets/{EditorPage-7PZzkNBT.js → EditorPage-CDIJXC4T.js} +1 -1
  29. package/apps/web/dist/assets/{FlowPreview-C_x5Kc2j.js → FlowPreview-BZLnG7GV.js} +1 -1
  30. package/apps/web/dist/assets/{Harness-CvvtSTZC.js → Harness-CNh3nbB_.js} +1 -1
  31. package/apps/web/dist/assets/{NewWizardChannels-g1qCd_tQ.js → NewWizardChannels-C1Ss9UMY.js} +1 -1
  32. package/apps/web/dist/assets/{NewWizardPage-B3hswj5r.js → NewWizardPage-2qLAbvDL.js} +1 -1
  33. package/apps/web/dist/assets/OnboardingPage-C1FJwEsT.js +1 -0
  34. package/apps/web/dist/assets/{ProjectPage-CFDncRxT.js → ProjectPage-CGuLUuOs.js} +1 -1
  35. package/apps/web/dist/assets/{PublicRunner-C9N5r-sT.js → PublicRunner-BKw1lOW4.js} +1 -1
  36. package/apps/web/dist/assets/{ReadOnly-C1UcqOlS.js → ReadOnly-DTjv2Jzm.js} +1 -1
  37. package/apps/web/dist/assets/{RunDrawer-B8YzFvgz.js → RunDrawer-D1I5xqVf.js} +1 -1
  38. package/apps/web/dist/assets/{RunnerView-ii-PP5c-.js → RunnerView-BPPmlv9z.js} +1 -1
  39. package/apps/web/dist/assets/{SettingsPage-ClEP5Q0t.js → SettingsPage-zbomQfGy.js} +1 -1
  40. package/apps/web/dist/assets/SetupPage-D3F7M6Pz.js +1 -0
  41. package/apps/web/dist/assets/{SharePage-BV2S0g84.js → SharePage-BY49IJgT.js} +1 -1
  42. package/apps/web/dist/assets/changelog-DYZC2E6q.js +1 -0
  43. package/apps/web/dist/assets/{circle-alert-D-Q6DK7b.js → circle-alert-CVOH4wAv.js} +1 -1
  44. package/apps/web/dist/assets/{esm-CTna4iL0.js → esm-BfXdeWaI.js} +1 -1
  45. package/apps/web/dist/assets/index-B9xVkr2X.css +1 -0
  46. package/apps/web/dist/assets/index-BH0PYgov.js +15 -0
  47. package/apps/web/dist/assets/{lock-DwGN_KOC.js → lock-DHBh62LA.js} +1 -1
  48. package/apps/web/dist/assets/{phone-XIVIe17d.js → phone-Bt1cyWpY.js} +1 -1
  49. package/apps/web/dist/assets/{settings-menu-JuSRq6NP.js → settings-menu-ace1vI3i.js} +1 -1
  50. package/apps/web/dist/assets/{ui-DrjXmHdO.js → ui-D2SqIZeQ.js} +1 -1
  51. package/apps/web/dist/assets/{upload-CDxTpAqx.js → upload-CCEq88l4.js} +1 -1
  52. package/apps/web/dist/index.html +3 -3
  53. package/apps/web/dist/install.sh +17 -7
  54. package/apps/web/dist/mcp/flow.html +2 -2
  55. package/package.json +1 -1
  56. package/apps/web/dist/assets/SetupPage-CDFzo6LT.js +0 -1
  57. package/apps/web/dist/assets/changelog-wZI-UaUi.js +0 -1
  58. package/apps/web/dist/assets/index-DUjJx-uk.css +0 -1
  59. package/apps/web/dist/assets/index-DnQgOKOQ.js +0 -15
@@ -84,7 +84,7 @@ async function call(path, token) {
84
84
  signal: AbortSignal.timeout(60_000),
85
85
  }).catch(() => null);
86
86
  if (!res) {
87
- throw new ProModuleError("Dein engenty-Konto ist gerade nicht erreichbar.", 502, "offline");
87
+ throw new ProModuleError("Your engenty account is not reachable right now.", 502, "offline");
88
88
  }
89
89
  return res;
90
90
  }
@@ -109,19 +109,19 @@ export async function refreshPro() {
109
109
  try {
110
110
  const token = await accountToken();
111
111
  if (!token) {
112
- throw new ProModuleError("Dein engenty-Konto ist gerade nicht erreichbar.", 502, "offline");
112
+ throw new ProModuleError("Your engenty account is not reachable right now.", 502, "offline");
113
113
  }
114
114
  const res = await call("", token);
115
115
  if (res.status === 401) {
116
- throw new ProModuleError("Das engenty-Konto nimmt diese Anmeldung nicht mehr an.", 403);
116
+ throw new ProModuleError("The engenty account no longer accepts this sign-in.", 403);
117
117
  }
118
118
  if (!res.ok) {
119
- throw new ProModuleError(`Das Konto antwortet nicht wie erwartet (${res.status}).`, 502);
119
+ throw new ProModuleError(`The account did not answer as expected (${res.status}).`, 502);
120
120
  }
121
121
  const answer = (await res.json());
122
122
  const claims = await verifySigned(answer.entitlement?.token ?? "", [AUDIENCE], env.local.accountUrl);
123
123
  if (!claims || claims.sub !== account.tenantId || !Array.isArray(claims.modules)) {
124
- throw new ProModuleError("Die Bestätigung des Pakets ließ sich nicht prüfen.", 502);
124
+ throw new ProModuleError("The package's confirmation could not be checked.", 502);
125
125
  }
126
126
  listing = answer;
127
127
  lastError = null;
@@ -177,7 +177,7 @@ function filesOf(zip) {
177
177
  files = unzipSync(zip);
178
178
  }
179
179
  catch {
180
- throw new ProModuleError("Das Paket ist beschädigt.", 502);
180
+ throw new ProModuleError("The package is damaged.", 502);
181
181
  }
182
182
  const out = {};
183
183
  for (const [name, data] of Object.entries(files)) {
@@ -188,7 +188,7 @@ function filesOf(zip) {
188
188
  const safe = parts.every((p) => p && p !== "." && p !== ".." && !p.includes("\\"));
189
189
  const allowed = name === MANIFEST_FILE || PARTS.some((part) => name.startsWith(part));
190
190
  if (!(safe && allowed)) {
191
- throw new ProModuleError(`Das Paket enthält eine unerlaubte Datei: ${name}`, 502);
191
+ throw new ProModuleError(`The package holds a file it may not: ${name}`, 502);
192
192
  }
193
193
  out[name] = data;
194
194
  }
@@ -197,28 +197,28 @@ function filesOf(zip) {
197
197
  /** Fetches one module of the plan, checks it and puts it in place; then it loads. */
198
198
  export async function installPro(id) {
199
199
  if (managed) {
200
- throw new ProModuleError("Hier nicht verfügbar.", 404, "not_found");
200
+ throw new ProModuleError("Not available here.", 404, "not_found");
201
201
  }
202
202
  const token = await accountToken();
203
203
  if (!token) {
204
- throw new ProModuleError("Verbinde zuerst dein engenty-Konto (Einstellungen → Konto).", 409);
204
+ throw new ProModuleError("Sign in to your engenty account first (Settings → Account).", 409);
205
205
  }
206
206
  if (!listing) {
207
207
  await refreshPro();
208
208
  }
209
209
  const entry = listing?.modules.find((m) => m.id === id);
210
210
  if (!entry) {
211
- throw new ProModuleError(`Für ${runtimeTag()} gibt es dieses Modul nicht.`, 404, "not_found");
211
+ throw new ProModuleError(`There is no build of this module for ${runtimeTag()}.`, 404, "not_found");
212
212
  }
213
213
  if (!entry.included) {
214
- throw new ProModuleError("Dieses Modul ist nicht Teil deines Pakets.", 403, "plan");
214
+ throw new ProModuleError("This module is not part of your plan.", 403, "plan");
215
215
  }
216
216
  const res = await call(`/${encodeURIComponent(id)}/package`, token);
217
217
  if (!res.ok) {
218
- throw new ProModuleError(`Das Modul ließ sich nicht laden (${res.status}).`, 502);
218
+ throw new ProModuleError(`The module could not be fetched (${res.status}).`, 502);
219
219
  }
220
220
  if (Number(res.headers.get("content-length") ?? 0) > MAX_PACKAGE) {
221
- throw new ProModuleError("Das Paket ist zu groß.", 502);
221
+ throw new ProModuleError("The package is too large.", 502);
222
222
  }
223
223
  const zip = new Uint8Array(await res.arrayBuffer());
224
224
  const sha256 = createHash("sha256").update(zip).digest("hex");
@@ -231,12 +231,12 @@ export async function installPro(id) {
231
231
  signature: entry.signature,
232
232
  });
233
233
  if (zip.length > MAX_PACKAGE || !genuine) {
234
- throw new ProModuleError("Das Paket ist nicht von engenty signiert und wurde verworfen.", 502);
234
+ throw new ProModuleError("The package is not signed by engenty and was discarded.", 502);
235
235
  }
236
236
  const files = filesOf(zip);
237
237
  const manifest = JSON.parse(new TextDecoder().decode(files[MANIFEST_FILE] ?? new Uint8Array()));
238
238
  if (manifest?.id !== id) {
239
- throw new ProModuleError("Das Paket passt nicht zu diesem Modul.", 502);
239
+ throw new ProModuleError("The package does not belong to this module.", 502);
240
240
  }
241
241
  const dir = proModulesDir();
242
242
  const target = join(dir, id);
@@ -270,7 +270,7 @@ export async function installPro(id) {
270
270
  /** Removes an installed module; its tables and what is in them stay. */
271
271
  export async function removePro(id) {
272
272
  if (managed || !(await installedIds()).includes(id)) {
273
- throw new ProModuleError("Dieses Modul ist nicht installiert.", 404, "not_found");
273
+ throw new ProModuleError("This module is not installed.", 404, "not_found");
274
274
  }
275
275
  await rm(join(proModulesDir(), id), { recursive: true, force: true });
276
276
  await findNewPlugins();
@@ -30,14 +30,14 @@ import { appleStatus } from "../harness/apple.js";
30
30
  import { freshAuth, loginEnv } from "../harness/env.js";
31
31
  import { detectHarness, detectHarnesses, HARNESS_IDS, harness, installSpec, } from "../harness/index.js";
32
32
  import { closeTerminal, openTerminal, resizeTerminal, subscribeTerminal, writeTerminal, } from "../harness/terminal.js";
33
- import { managed, tenantInfo, tenantMembers, userInfo } from "../manage.js";
33
+ import { installMail, managed, renameTenant, tenantInfo, tenantMembers, userInfo, } from "../manage.js";
34
34
  import { seenApps } from "../mcp/seen.js";
35
35
  import { generateImageMedia, generateSpeechMedia, generateVideoMedia } from "../media/generate.js";
36
36
  import { transcribeAudio } from "../media/transcribe.js";
37
37
  import { checkKey, classProblem, classWays, embeddingModel, hasTextModel, LOCAL_KEYS, localModelSettings, ModelUnavailableError, modelSettings, saveLocalModels, saveModels, storedKey, textModel, } from "../models.js";
38
38
  import { refreshPro } from "../plugins/pro.js";
39
39
  import { HTML_RESPONSE_CSP } from "../render/guard.js";
40
- import { isAdminRole, mayBuild, mayCreate, projectWritable, requireWritable, } from "../services/access.js";
40
+ import { isAdminRole, mayBuild, mayCreate, projectWritable, requireAdmin, requireWritable, } from "../services/access.js";
41
41
  import { architectTurn } from "../services/architect.js";
42
42
  import { addMessage, assistantLayout, currentChat, earlierChats, foldChat, newChat, openChat, readChat, turnHistory, } from "../services/assistant-chats.js";
43
43
  import { checkForCloud, cloudLinked, cloudSpaces, cloudState, forgetCloud, publishAndSync, pushSharing, removeFromCloud, replaceCloudSpaces, rotateInCloud, syncToCloud, } from "../services/cloud.js";
@@ -45,6 +45,7 @@ import { notFound, ServiceError } from "../services/errors.js";
45
45
  import { deleteFile, listFiles, readFile, writeFile } from "../services/files.js";
46
46
  import { categoryContents, listKnowledge, resolvePath, valueContents, } from "../services/knowledge.js";
47
47
  import { writeSummary } from "../services/knowledge-model.js";
48
+ import { applyWebsite, finishOnboarding, needsOnboarding } from "../services/onboarding.js";
48
49
  import { exportWizard, importWizard } from "../services/package.js";
49
50
  import { profileSchema, saveProfile, userProfile } from "../services/profile.js";
50
51
  import { addProjectFile, addProjectFileFromUrl, fileView, orderProjectFiles, projectFile, projectFileContent, projectFiles, reindexProjectFile, removeProjectFile, updateProjectFile, } from "../services/project-files.js";
@@ -232,6 +233,8 @@ export const studio = new Hono()
232
233
  ? {
233
234
  name: linked.name,
234
235
  email: linked.email,
236
+ /** The team the account's space belongs to, as the Manage-App names it. */
237
+ team: overview?.tenant.name ?? null,
235
238
  credits: overview?.tenant.balanceCredits ?? null,
236
239
  /** What of the credits ends on a date, the nearest first. */
237
240
  expiring: overview?.tenant.expiring ?? [],
@@ -249,6 +252,8 @@ export const studio = new Hono()
249
252
  subscriptions: managed ? [] : await subscriptionClients(),
250
253
  /** A runtime that runs alone keeps its setup in front until a test call has worked on the chosen source and the way is still open. */
251
254
  setupDone: managed ? true : await setupDone(),
255
+ /** The cloud studio's first visit: the short wizard that names the team and fills the space (services/onboarding.ts). */
256
+ onboarding: await needsOnboarding(user),
252
257
  /** What answers the studio chat: a model of class `highest`, or the admin's own subscription. */
253
258
  chatEngine: managed ? "models" : await chatEngine(await hasTextModel()),
254
259
  aiReady: (await hasTextModel()) || (!managed && (await subscriptionClients()).length > 0),
@@ -1392,6 +1397,40 @@ export const studio = new Hono()
1392
1397
  })
1393
1398
  // The address the system browser opens: the account's sign-in, or — for someone without an
1394
1399
  // account — its sign-up page with the invitation code, which then goes on to the sign-in.
1400
+ // --- the first visit of a cloud studio: who the team is, its website, first documents -----
1401
+ .put("/team", async (c) => {
1402
+ if (!managed) {
1403
+ return c.json({ error: "not_managed" }, 404);
1404
+ }
1405
+ await requireAdmin();
1406
+ const { name } = z.object({ name: z.string().trim().min(1).max(80) }).parse(await c.req.json());
1407
+ const info = await renameTenant(c.get("user").tenantId, name);
1408
+ return c.json({ name: info.name });
1409
+ })
1410
+ .post("/onboarding/done", async (c) => {
1411
+ if (!managed) {
1412
+ return c.json({ error: "not_managed" }, 404);
1413
+ }
1414
+ await finishOnboarding(c.get("user").tenantId);
1415
+ return c.json({ ok: true });
1416
+ })
1417
+ .post("/projects/:id/website", async (c) => {
1418
+ const user = c.get("user");
1419
+ const project = await ownedProject(user.id, c.req.param("id"));
1420
+ const { url } = z.object({ url: z.string().trim().min(3).max(400) }).parse(await c.req.json());
1421
+ return c.json(await applyWebsite(user.id, project.id, url));
1422
+ })
1423
+ // The install command and the first steps, mailed to the signed-in person by the Manage-App.
1424
+ .post("/install-mail", async (c) => {
1425
+ if (!managed) {
1426
+ return c.json({ error: "not_managed" }, 404);
1427
+ }
1428
+ const { lang } = z
1429
+ .object({ lang: z.enum(["de", "en"]).default("en") })
1430
+ .parse(await c.req.json().catch(() => ({})));
1431
+ await installMail(c.get("user").email, lang);
1432
+ return c.json({ ok: true });
1433
+ })
1395
1434
  .post("/account/link", async (c) => {
1396
1435
  if (managed) {
1397
1436
  return c.notFound();
@@ -25,7 +25,7 @@ export async function cloudState(wizardId) {
25
25
  async function call(method, path, body, timeoutMs = 30_000) {
26
26
  const token = await accountToken();
27
27
  if (!token) {
28
- throw new ServiceError("refused", "Das Konto ist nicht mehr angemeldet. Bitte neu anmelden.", {
28
+ throw new ServiceError("refused", "The account is signed out. Please sign in again.", {
29
29
  reason: "signed_out",
30
30
  });
31
31
  }
@@ -39,7 +39,7 @@ async function call(method, path, body, timeoutMs = 30_000) {
39
39
  signal: AbortSignal.timeout(timeoutMs),
40
40
  }).catch(() => null);
41
41
  if (!res) {
42
- throw new ServiceError("refused", "Die Cloud ist gerade nicht erreichbar.", {
42
+ throw new ServiceError("refused", "The cloud is not reachable right now.", {
43
43
  reason: "unreachable",
44
44
  });
45
45
  }
@@ -49,7 +49,7 @@ async function call(method, path, body, timeoutMs = 30_000) {
49
49
  function refusal(answer, fallback) {
50
50
  const { error, reason, ...rest } = answer.body;
51
51
  const message = answer.status === 401
52
- ? "Das Konto ist nicht mehr angemeldet. Bitte neu anmelden."
52
+ ? "The account is signed out. Please sign in again."
53
53
  : typeof error === "string" && error
54
54
  ? error
55
55
  : fallback;
@@ -213,7 +213,7 @@ export async function syncToCloud(userId, wizardId) {
213
213
  const w = await ownedWizard(userId, wizardId);
214
214
  const version = await publishedVersion(w);
215
215
  if (!version) {
216
- throw new ServiceError("refused", "Bitte den Wizard zuerst veröffentlichen.");
216
+ throw new ServiceError("refused", "Publish the wizard first.");
217
217
  }
218
218
  const before = await cloudState(w.id);
219
219
  try {
@@ -231,7 +231,7 @@ export async function syncToCloud(userId, wizardId) {
231
231
  dailyRunLimit: w.dailyRunLimit,
232
232
  }, 120_000);
233
233
  if (!answer.ok || !answer.body.shareUrl) {
234
- throw refusal(answer, "Die Cloud hat den Wizard nicht angenommen.");
234
+ throw refusal(answer, "The cloud did not take the wizard.");
235
235
  }
236
236
  const state = {
237
237
  copy: {
@@ -255,7 +255,7 @@ export async function syncToCloud(userId, wizardId) {
255
255
  const failed = {
256
256
  copy: before.copy,
257
257
  error: {
258
- message: err instanceof ServiceError ? err.message : "Das Senden hat nicht geklappt.",
258
+ message: err instanceof ServiceError ? err.message : "Sending did not work.",
259
259
  reason: err instanceof ServiceError ? err.data.reason : undefined,
260
260
  at: now.toISOString(),
261
261
  tries,
@@ -309,7 +309,7 @@ export async function rotateInCloud(userId, wizardId) {
309
309
  const w = await ownedWizard(userId, wizardId);
310
310
  const answer = await call("POST", `/spaces/${w.projectId}/wizards/${w.id}/rotate-link`);
311
311
  if (!answer.ok || !answer.body.shareUrl) {
312
- throw refusal(answer, "Der Link in der Cloud ließ sich nicht erneuern.");
312
+ throw refusal(answer, "The link in the cloud could not be renewed.");
313
313
  }
314
314
  const next = {
315
315
  ...state,
@@ -416,7 +416,7 @@ export async function checkForCloud(userId, wizardId) {
416
416
  files: files.map((f) => f.path),
417
417
  });
418
418
  if (!answer.ok) {
419
- throw refusal(answer, "Die Cloud hat nicht geantwortet.");
419
+ throw refusal(answer, "The cloud did not answer.");
420
420
  }
421
421
  const documents = await projectFiles(w.projectId, "document");
422
422
  return {
@@ -428,7 +428,7 @@ export async function checkForCloud(userId, wizardId) {
428
428
  export async function cloudSpaces() {
429
429
  const answer = await call("GET", "/spaces");
430
430
  if (!answer.ok) {
431
- throw refusal(answer, "Die Cloud hat nicht geantwortet.");
431
+ throw refusal(answer, "The cloud did not answer.");
432
432
  }
433
433
  return answer.body.spaces ?? [];
434
434
  }
@@ -446,7 +446,7 @@ export async function replaceCloudSpaces(userId) {
446
446
  if (!mine.has(space.id)) {
447
447
  const answer = await call("DELETE", `/spaces/${space.id}`);
448
448
  if (!answer.ok) {
449
- throw refusal(answer, "Das Projekt in der Cloud ließ sich nicht entfernen.");
449
+ throw refusal(answer, "The space in the cloud could not be removed.");
450
450
  }
451
451
  }
452
452
  }
@@ -0,0 +1,152 @@
1
+ import { readWebsite } from "../agents/website.js";
2
+ import { managed } from "../manage.js";
3
+ import { readSetting, writeSetting } from "../settings.js";
4
+ import { isAdminRole } from "./access.js";
5
+ import { addProjectFile, projectFiles } from "./project-files.js";
6
+ import { listProjects, updateProject } from "./projects.js";
7
+ /**
8
+ * The first visit of a team's studio in the cloud: a short wizard asks who the team is, reads
9
+ * its website into the space, takes first documents and explains the space. It shows once, to
10
+ * the people who may change the team, and never to a team that already has wizards; the mark
11
+ * that it is done sits in the control database under the tenant.
12
+ */
13
+ const key = (tenantId) => `onboarding:${tenantId}`;
14
+ export async function needsOnboarding(user) {
15
+ if (!managed || !isAdminRole(user.role)) {
16
+ return false;
17
+ }
18
+ if (await readSetting(key(user.tenantId))) {
19
+ return false;
20
+ }
21
+ const projects = await listProjects(user.id);
22
+ return projects.every((p) => p.wizardCount === 0);
23
+ }
24
+ export async function finishOnboarding(tenantId) {
25
+ await writeSetting(key(tenantId), { doneAt: new Date().toISOString() });
26
+ }
27
+ /** A hex colour as `#rrggbb`, or null when the value is no plain colour. */
28
+ function hex(value) {
29
+ const v = value.trim().toLowerCase();
30
+ const six = v.match(/^#([0-9a-f]{6})\b/);
31
+ if (six) {
32
+ return `#${six[1]}`;
33
+ }
34
+ const three = v.match(/^#([0-9a-f]{3})\b/);
35
+ if (three) {
36
+ return `#${[...three[1]].map((c) => c + c).join("")}`;
37
+ }
38
+ const rgb = v.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
39
+ if (rgb) {
40
+ const part = (n) => Math.min(255, Number(n)).toString(16).padStart(2, "0");
41
+ return `#${part(rgb[1])}${part(rgb[2])}${part(rgb[3])}`;
42
+ }
43
+ return null;
44
+ }
45
+ /** Greys and near-whites say nothing about a brand. */
46
+ function telling(color) {
47
+ const r = Number.parseInt(color.slice(1, 3), 16);
48
+ const g = Number.parseInt(color.slice(3, 5), 16);
49
+ const b = Number.parseInt(color.slice(5, 7), 16);
50
+ const spread = Math.max(r, g, b) - Math.min(r, g, b);
51
+ const light = (r + g + b) / 3;
52
+ return spread > 24 && light > 24 && light < 235;
53
+ }
54
+ /** A page title is often "Company – Slogan" or "Home | Company": the company's part of it. */
55
+ export function companyOf(title) {
56
+ const parts = title
57
+ .split(/\s+[–—|·-]\s+|:\s+/)
58
+ .map((p) => p.trim())
59
+ .filter(Boolean);
60
+ if (parts.length < 2) {
61
+ return title.trim().slice(0, 120);
62
+ }
63
+ const generic = /^(home|start|startseite|willkommen|welcome)$/i;
64
+ const named = parts.filter((p) => !generic.test(p));
65
+ // The shortest telling part is the name; a slogan is longer.
66
+ return (named.sort((a, b) => a.length - b.length)[0] ?? parts[0]).slice(0, 120);
67
+ }
68
+ /** The first paragraph of the page's text that reads like prose, as the about text. */
69
+ export function aboutOf(description, text) {
70
+ if (description.trim().length >= 40) {
71
+ return description.trim().slice(0, 600);
72
+ }
73
+ const paragraph = text
74
+ .split(/\n{2,}/)
75
+ .map((p) => p.replace(/^[#>*\-\s]+/, "").trim())
76
+ .find((p) => p.length >= 80 && !p.startsWith("[") && !/^!\[/.test(p));
77
+ return (paragraph ?? description.trim()).slice(0, 600);
78
+ }
79
+ /**
80
+ * Up to three brand colours out of what the site declares and uses: the theme colour first, then
81
+ * the stylesheet's named colours, then the most used ones; greys and near-whites left out.
82
+ */
83
+ export function brandColors(brand) {
84
+ const candidates = [
85
+ ...(brand.themeColor ? [{ name: "Brand", value: brand.themeColor }] : []),
86
+ ...brand.variables,
87
+ ...brand.frequent.map((value, i) => ({ name: `Colour ${i + 1}`, value })),
88
+ ];
89
+ const colors = [];
90
+ for (const c of candidates) {
91
+ const value = hex(c.value);
92
+ if (value && telling(value) && !colors.some((x) => x.value === value)) {
93
+ colors.push({ name: c.name.replace(/^--/, "").slice(0, 120) || "Colour", value });
94
+ }
95
+ if (colors.length === 3) {
96
+ break;
97
+ }
98
+ }
99
+ return colors;
100
+ }
101
+ /**
102
+ * Reads a website into the space's Info & brand: the company's name, what it does, up to three
103
+ * of its colours and, where the space has none yet, its logo. What the assistant does on
104
+ * request, done once at the start without a model.
105
+ */
106
+ export async function applyWebsite(userId, projectId, url) {
107
+ const reading = await readWebsite(url, AbortSignal.timeout(30_000));
108
+ const name = companyOf(reading.title || new URL(reading.url).hostname);
109
+ const about = aboutOf(reading.description, reading.text);
110
+ const colors = brandColors(reading.brand);
111
+ await updateProject(userId, projectId, {
112
+ brand: {
113
+ name,
114
+ ...(about ? { about } : {}),
115
+ ...(colors.length ? { colors } : {}),
116
+ },
117
+ });
118
+ let logo = false;
119
+ const first = reading.brand.logos[0];
120
+ if (first && (await projectFiles(projectId, "logo")).length === 0) {
121
+ logo = await fetchLogo(projectId, first.url, first.hint);
122
+ }
123
+ return { name, about: Boolean(about), colors: colors.length, logo };
124
+ }
125
+ const LOGO_BYTES = 5 * 1024 * 1024;
126
+ async function fetchLogo(projectId, url, hint) {
127
+ try {
128
+ const res = await fetch(url, { signal: AbortSignal.timeout(15_000) });
129
+ const mime = res.headers.get("content-type")?.split(";")[0].trim().toLowerCase() ?? "";
130
+ if (!res.ok || !mime.startsWith("image/")) {
131
+ return false;
132
+ }
133
+ const data = new Uint8Array(await res.arrayBuffer());
134
+ if (data.byteLength === 0 || data.byteLength > LOGO_BYTES) {
135
+ return false;
136
+ }
137
+ const name = decodeURIComponent(new URL(url).pathname.split("/").pop() || "logo");
138
+ await addProjectFile(projectId, {
139
+ kind: "logo",
140
+ name,
141
+ mime,
142
+ data,
143
+ description: hint || undefined,
144
+ source: url,
145
+ });
146
+ return true;
147
+ }
148
+ catch {
149
+ // A logo that cannot be fetched is no loss: the person adds one under Space → Logos.
150
+ return false;
151
+ }
152
+ }
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{t as r}from"./logo-C4V2_3Ar.js";import{t as i}from"./preload-helper-CNEI7N0N.js";import{$t as a,At as o,Et as s,Mt as c,Ot as l,gt as u,ht as d,in as f,mt as p,pt as m,wt as h,xt as g}from"./ui-DrjXmHdO.js";import{ft as _,pt as v,wt as y}from"./index-DnQgOKOQ.js";import{c as b,f as x}from"./settings-menu-JuSRq6NP.js";import{ReleaseNotes as S,loadReleases as C,releaseDate as w,releaseLabel as T}from"./ChangelogDialog-DsSEkayM.js";var E=e(t(),1),D=[{name:`engenty wizards`,description:{de:`KI-Wizards aus einer Beschreibung, mit einem Link geteilt.`,en:`AI wizards built from a description, shared with a link.`},homepage:`https://github.com/engenty/wizards`,license:`FSL-1.1-MIT`},{name:`engenty`,description:{de:`Konnektoren, Datentabellen, Suche und die Engenties stammen aus dem engenty-Framework.`,en:`Connectors, data tables, search and the engenties come from the engenty framework.`},homepage:`https://github.com/engenty/engenty`,license:`FSL-1.1-MIT`}],O=[{name:`Mastra`,description:{de:`Agent-Framework hinter den KI-Schritten.`,en:`Agent framework behind the AI steps.`},homepage:`https://github.com/mastra-ai/mastra`,license:`Apache-2.0`},{name:`AI SDK`,description:{de:`Modell-Aufrufe für Text, Bild, Video und Sprache.`,en:`Model calls for text, image, video and speech.`},homepage:`https://github.com/vercel/ai`,license:`Apache-2.0`},{name:`Model Context Protocol`,description:{de:`MCP-Server zum Bauen von Wizards, MCP-Client für Werkzeuge der Schritte.`,en:`MCP server for building wizards, MCP client for the steps' tools.`},homepage:`https://github.com/modelcontextprotocol/typescript-sdk`,license:`MIT`},{name:`Hono`,description:{de:`HTTP-API der Runtime.`,en:`The runtime's HTTP API.`},homepage:`https://github.com/honojs/hono`,license:`MIT`},{name:`Drizzle ORM`,description:{de:`Schema und Migrationen der Datenbanken.`,en:`Schema and migrations of the databases.`},homepage:`https://github.com/drizzle-team/drizzle-orm`,license:`Apache-2.0`},{name:`libSQL`,description:{de:`Eine Datenbank je Mandant, lokal als Datei oder bei Turso.`,en:`One database per tenant, a local file or at Turso.`},homepage:`https://github.com/tursodatabase/libsql`,license:`MIT`},{name:`Playwright`,description:{de:`Browser-Schritte sowie PDF- und PNG-Export.`,en:`Browser steps and the PDF and PNG export.`},homepage:`https://github.com/microsoft/playwright`,license:`Apache-2.0`},{name:`agentOS`,description:{de:`Sandbox für Code-Schritte ohne Docker.`,en:`Sandbox for code steps without Docker.`},homepage:`https://github.com/rivet-dev/agentos`,license:`Apache-2.0`},{name:`React`,description:{de:`UI-Bibliothek der Web-App.`,en:`UI library of the web app.`},homepage:`https://github.com/facebook/react`,license:`MIT`},{name:`Vite`,description:{de:`Build-Werkzeug der Web-App.`,en:`Build tool of the web app.`},homepage:`https://github.com/vitejs/vite`,license:`MIT`},{name:`Tailwind CSS`,description:{de:`Styling der Oberfläche.`,en:`Styling of the interface.`},homepage:`https://github.com/tailwindlabs/tailwindcss`,license:`MIT`},{name:`React Flow`,description:{de:`Das Diagramm der Schritte im Editor.`,en:`The diagram of steps in the editor.`},homepage:`https://github.com/xyflow/xyflow`,license:`MIT`},{name:`TanStack Query`,description:{de:`Server-Daten in der Web-App.`,en:`Server data in the web app.`},homepage:`https://github.com/TanStack/query`,license:`MIT`},{name:`xterm.js`,description:{de:`Das Terminal auf der Seite, in dem sich KI-Clients anmelden.`,en:`The terminal on the page where AI clients sign in.`},homepage:`https://github.com/xtermjs/xterm.js`,license:`MIT`},{name:`Lucide`,description:{de:`Icons.`,en:`Icons.`},homepage:`https://github.com/lucide-icons/lucide`,license:`ISC`},{name:`Geist & Geist Mono`,description:{de:`Schrift der Oberfläche.`,en:`Typeface of the interface.`},homepage:`https://github.com/vercel/geist-font`,license:`OFL-1.1`},{name:`Space Grotesk`,description:{de:`Schrift der Überschriften.`,en:`Typeface of the headings.`},homepage:`https://github.com/floriankarsten/space-grotesk`,license:`OFL-1.1`},{name:`git-cliff`,description:{de:`Erzeugt den Changelog aus den Commits.`,en:`Generates the changelog from the commits.`},homepage:`https://github.com/orhun/git-cliff`,license:`MIT OR Apache-2.0`}],k=e(n(),1),A=(e,...t)=>t.some(t=>t?.toLowerCase().includes(e));function j({name:e,homepage:t,version:n,license:r,description:i}){return(0,k.jsxs)(`li`,{className:`py-2.5`,children:[(0,k.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2.5 gap-y-0.5`,children:[t?(0,k.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,k.jsx)(a,{"aria-hidden":!0,className:`size-3 text-ink-4`})]}):(0,k.jsx)(`span`,{className:`font-medium text-[0.875rem] text-ink`,children:e}),n?(0,k.jsx)(`span`,{className:`text-[0.75rem] text-ink-3 tabular-nums`,children:n}):null,(0,k.jsx)(`span`,{className:`text-[0.75rem] text-ink-3`,children:r})]}),i?(0,k.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:i}):null]})}function M({title:e,hint:t,children:n}){return(0,k.jsxs)(`section`,{className:`mt-6`,children:[(0,k.jsx)(`h3`,{className:`border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:e}),t?(0,k.jsx)(`p`,{className:`mt-2 text-[0.8125rem] text-ink-3`,children:t}):null,n]})}function N({credits:e}){return(0,k.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:e.map(e=>(0,k.jsx)(j,{name:e.name,homepage:e.homepage,license:e.license,description:e.description[l]},e.name))})}function P({label:e,packages:t}){return(0,k.jsxs)(`div`,{className:`mt-4`,children:[(0,k.jsx)(`h4`,{className:`font-medium text-[0.75rem] text-ink-3 tracking-wide`,children:e}),(0,k.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:t.map(e=>(0,k.jsx)(j,{...e},e.name))})]})}function F({active:e}){let[t,n]=(0,E.useState)(null),[r,a]=(0,E.useState)(``);(0,E.useEffect)(()=>{if(!e||t)return;let r=!1;return i(()=>import(`./oss-credits-BQQX0kvk.js`).then(e=>{r||n(e.default)}),[]),()=>{r=!0}},[e,t]),(0,E.useEffect)(()=>{e||a(``)},[e]);let s=r.trim().toLowerCase(),c=e=>s?e.filter(e=>A(s,e.name,e.license,e.description.de,e.description.en)):e,l=e=>s?e.filter(e=>A(s,e.name,e.license,e.version)):e,d=c(D),f=c(O),m=t?[{id:`shared`,label:o(`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):[],h=d.length===0&&f.length===0&&m.length===0;return(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`p`,{className:`mb-4 text-[0.875rem] text-ink-3`,children:o(`about.creditsHint`)}),(0,k.jsx)(u,{type:`search`,value:r,placeholder:o(`about.search`),onChange:e=>a(e.target.value)}),d.length>0?(0,k.jsx)(M,{title:o(`about.creditsProduct`),children:(0,k.jsx)(N,{credits:d})}):null,f.length>0?(0,k.jsx)(M,{title:o(`about.creditsBuiltWith`),children:(0,k.jsx)(N,{credits:f})}):null,t===null?(0,k.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,k.jsx)(g,{})}):m.length>0?(0,k.jsx)(M,{title:o(`about.creditsDeps`),hint:s?void 0:o(`about.creditsDepsHint`),children:m.map(e=>(0,k.jsx)(P,{label:e.label,packages:e.packages},e.id))}):null,t!==null&&h?(0,k.jsx)(p,{children:o(`about.noMatches`)}):null]})}var I=[`new`,`earlier`,`credits`],L=e=>o(e===`new`?`about.tab.new`:e===`earlier`?`about.tab.earlier`:`about.credits`),R=e=>e===1?o(`about.change`):o(`about.changes`,{n:e});function z({open:e,onClose:t,me:n}){let i=n?.mode===`local`,{data:a,latest:l}=v(i&&e),[u,p]=(0,E.useState)(null),[D,O]=(0,E.useState)(`new`),A=x(I.indexOf(D)),j=a?.newer&&l?l:y;(0,E.useEffect)(()=>{if(!e)return;let t=!1;return p(null),C(j===`0.3.8`?void 0:j).then(e=>{t||p(e)}),()=>{t=!0}},[e,j]);let M=u?.find(e=>e.version===`v${j}`)??u?.[0]??null,N=u?.filter(e=>e!==M)??[],P=i?a?.kind??null:`cloud`;return(0,k.jsxs)(m,{open:e,onClose:t,wide:!0,height:`tall`,children:[(0,k.jsx)(`div`,{className:`-mt-2 -mr-2 sticky top-0 z-10 flex h-0 justify-end`,children:(0,k.jsx)(d,{label:o(`common.close`),onClick:t,children:(0,k.jsx)(c,{className:`size-4`})})}),(0,k.jsxs)(`div`,{className:`flex flex-col items-center pt-4 text-center`,children:[(0,k.jsx)(r,{size:96}),(0,k.jsxs)(`div`,{className:`mt-4 font-display font-semibold text-[1.5rem] tracking-tight`,children:[`engenty`,(0,k.jsx)(`span`,{className:`text-ember`,children:`.`}),(0,k.jsx)(`span`,{className:`ml-1.5 font-normal text-ink-3`,children:`wizards`})]}),(0,k.jsxs)(`div`,{className:`mt-1 text-[0.9375rem] text-ink-3 tabular-nums`,children:[o(`about.version`,{v:y}),P?` · ${o(`about.kind.${P}`)}`:``]})]}),i?(0,k.jsx)(`div`,{className:`mt-5`,children:(0,k.jsx)(_,{enabled:e})}):null,(0,k.jsx)(`div`,{className:`mt-6 flex justify-center`,children:(0,k.jsx)(h,{value:D,onChange:O,options:I.map(e=>({id:e,label:L(e)})),label:o(`about.title`)})}),(0,k.jsxs)(`div`,{className:s(`mt-5`,b(A)),children:[D===`new`?u===null?(0,k.jsx)(`div`,{className:`flex justify-center py-6 text-ink-3`,children:(0,k.jsx)(g,{})}):M?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:[T(M),(0,k.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] text-ink-3 tabular-nums`,children:w(M)})]}),(0,k.jsx)(`div`,{className:`mt-3`,children:(0,k.jsx)(S,{release:M})})]}):(0,k.jsx)(`p`,{className:`text-[0.875rem] text-ink-3`,children:o(`about.changelogEmpty`)}):null,D===`earlier`?(0,k.jsx)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:N.map(e=>(0,k.jsxs)(`details`,{className:`group/r py-2`,children:[(0,k.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-baseline gap-3 text-[0.875rem] [&::-webkit-details-marker]:hidden`,children:[(0,k.jsx)(f,{className:`size-3.5 shrink-0 self-center text-ink-4 transition group-open/r:rotate-90`}),(0,k.jsx)(`span`,{className:`font-medium text-ink tabular-nums`,children:T(e)}),(0,k.jsx)(`span`,{className:`text-[0.8125rem] text-ink-3 tabular-nums`,children:w(e)}),(0,k.jsx)(`span`,{className:`ml-auto text-[0.8125rem] text-ink-4`,children:R(e.commits.length)})]}),(0,k.jsx)(`div`,{className:`mt-2 pl-6`,children:(0,k.jsx)(S,{release:e})})]},e.version??`unreleased`))}):null,D===`credits`?(0,k.jsx)(F,{active:!0}):null]},D)]})}export{z as AboutDialog};
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{t as r}from"./logo-C4V2_3Ar.js";import{t as i}from"./preload-helper-CNEI7N0N.js";import{$t as a,At as o,Et as s,Mt as c,Ot as l,gt as u,ht as d,in as f,mt as p,pt as m,wt as h,xt as g}from"./ui-D2SqIZeQ.js";import{ft as _,pt as v,wt as y}from"./index-BH0PYgov.js";import{c as b,f as x}from"./settings-menu-ace1vI3i.js";import{ReleaseNotes as S,loadReleases as C,releaseDate as w,releaseLabel as T}from"./ChangelogDialog-DynvQuuR.js";var E=e(t(),1),D=[{name:`engenty wizards`,description:{de:`KI-Wizards aus einer Beschreibung, mit einem Link geteilt.`,en:`AI wizards built from a description, shared with a link.`},homepage:`https://github.com/engenty/wizards`,license:`FSL-1.1-MIT`},{name:`engenty`,description:{de:`Konnektoren, Datentabellen, Suche und die Engenties stammen aus dem engenty-Framework.`,en:`Connectors, data tables, search and the engenties come from the engenty framework.`},homepage:`https://github.com/engenty/engenty`,license:`FSL-1.1-MIT`}],O=[{name:`Mastra`,description:{de:`Agent-Framework hinter den KI-Schritten.`,en:`Agent framework behind the AI steps.`},homepage:`https://github.com/mastra-ai/mastra`,license:`Apache-2.0`},{name:`AI SDK`,description:{de:`Modell-Aufrufe für Text, Bild, Video und Sprache.`,en:`Model calls for text, image, video and speech.`},homepage:`https://github.com/vercel/ai`,license:`Apache-2.0`},{name:`Model Context Protocol`,description:{de:`MCP-Server zum Bauen von Wizards, MCP-Client für Werkzeuge der Schritte.`,en:`MCP server for building wizards, MCP client for the steps' tools.`},homepage:`https://github.com/modelcontextprotocol/typescript-sdk`,license:`MIT`},{name:`Hono`,description:{de:`HTTP-API der Runtime.`,en:`The runtime's HTTP API.`},homepage:`https://github.com/honojs/hono`,license:`MIT`},{name:`Drizzle ORM`,description:{de:`Schema und Migrationen der Datenbanken.`,en:`Schema and migrations of the databases.`},homepage:`https://github.com/drizzle-team/drizzle-orm`,license:`Apache-2.0`},{name:`libSQL`,description:{de:`Eine Datenbank je Mandant, lokal als Datei oder bei Turso.`,en:`One database per tenant, a local file or at Turso.`},homepage:`https://github.com/tursodatabase/libsql`,license:`MIT`},{name:`Playwright`,description:{de:`Browser-Schritte sowie PDF- und PNG-Export.`,en:`Browser steps and the PDF and PNG export.`},homepage:`https://github.com/microsoft/playwright`,license:`Apache-2.0`},{name:`agentOS`,description:{de:`Sandbox für Code-Schritte ohne Docker.`,en:`Sandbox for code steps without Docker.`},homepage:`https://github.com/rivet-dev/agentos`,license:`Apache-2.0`},{name:`React`,description:{de:`UI-Bibliothek der Web-App.`,en:`UI library of the web app.`},homepage:`https://github.com/facebook/react`,license:`MIT`},{name:`Vite`,description:{de:`Build-Werkzeug der Web-App.`,en:`Build tool of the web app.`},homepage:`https://github.com/vitejs/vite`,license:`MIT`},{name:`Tailwind CSS`,description:{de:`Styling der Oberfläche.`,en:`Styling of the interface.`},homepage:`https://github.com/tailwindlabs/tailwindcss`,license:`MIT`},{name:`React Flow`,description:{de:`Das Diagramm der Schritte im Editor.`,en:`The diagram of steps in the editor.`},homepage:`https://github.com/xyflow/xyflow`,license:`MIT`},{name:`TanStack Query`,description:{de:`Server-Daten in der Web-App.`,en:`Server data in the web app.`},homepage:`https://github.com/TanStack/query`,license:`MIT`},{name:`xterm.js`,description:{de:`Das Terminal auf der Seite, in dem sich KI-Clients anmelden.`,en:`The terminal on the page where AI clients sign in.`},homepage:`https://github.com/xtermjs/xterm.js`,license:`MIT`},{name:`Lucide`,description:{de:`Icons.`,en:`Icons.`},homepage:`https://github.com/lucide-icons/lucide`,license:`ISC`},{name:`Geist & Geist Mono`,description:{de:`Schrift der Oberfläche.`,en:`Typeface of the interface.`},homepage:`https://github.com/vercel/geist-font`,license:`OFL-1.1`},{name:`Space Grotesk`,description:{de:`Schrift der Überschriften.`,en:`Typeface of the headings.`},homepage:`https://github.com/floriankarsten/space-grotesk`,license:`OFL-1.1`},{name:`git-cliff`,description:{de:`Erzeugt den Changelog aus den Commits.`,en:`Generates the changelog from the commits.`},homepage:`https://github.com/orhun/git-cliff`,license:`MIT OR Apache-2.0`}],k=e(n(),1),A=(e,...t)=>t.some(t=>t?.toLowerCase().includes(e));function j({name:e,homepage:t,version:n,license:r,description:i}){return(0,k.jsxs)(`li`,{className:`py-2.5`,children:[(0,k.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2.5 gap-y-0.5`,children:[t?(0,k.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,k.jsx)(a,{"aria-hidden":!0,className:`size-3 text-ink-4`})]}):(0,k.jsx)(`span`,{className:`font-medium text-[0.875rem] text-ink`,children:e}),n?(0,k.jsx)(`span`,{className:`text-[0.75rem] text-ink-3 tabular-nums`,children:n}):null,(0,k.jsx)(`span`,{className:`text-[0.75rem] text-ink-3`,children:r})]}),i?(0,k.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:i}):null]})}function M({title:e,hint:t,children:n}){return(0,k.jsxs)(`section`,{className:`mt-6`,children:[(0,k.jsx)(`h3`,{className:`border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:e}),t?(0,k.jsx)(`p`,{className:`mt-2 text-[0.8125rem] text-ink-3`,children:t}):null,n]})}function N({credits:e}){return(0,k.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:e.map(e=>(0,k.jsx)(j,{name:e.name,homepage:e.homepage,license:e.license,description:e.description[l]},e.name))})}function P({label:e,packages:t}){return(0,k.jsxs)(`div`,{className:`mt-4`,children:[(0,k.jsx)(`h4`,{className:`font-medium text-[0.75rem] text-ink-3 tracking-wide`,children:e}),(0,k.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:t.map(e=>(0,k.jsx)(j,{...e},e.name))})]})}function F({active:e}){let[t,n]=(0,E.useState)(null),[r,a]=(0,E.useState)(``);(0,E.useEffect)(()=>{if(!e||t)return;let r=!1;return i(()=>import(`./oss-credits-BQQX0kvk.js`).then(e=>{r||n(e.default)}),[]),()=>{r=!0}},[e,t]),(0,E.useEffect)(()=>{e||a(``)},[e]);let s=r.trim().toLowerCase(),c=e=>s?e.filter(e=>A(s,e.name,e.license,e.description.de,e.description.en)):e,l=e=>s?e.filter(e=>A(s,e.name,e.license,e.version)):e,d=c(D),f=c(O),m=t?[{id:`shared`,label:o(`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):[],h=d.length===0&&f.length===0&&m.length===0;return(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`p`,{className:`mb-4 text-[0.875rem] text-ink-3`,children:o(`about.creditsHint`)}),(0,k.jsx)(u,{type:`search`,value:r,placeholder:o(`about.search`),onChange:e=>a(e.target.value)}),d.length>0?(0,k.jsx)(M,{title:o(`about.creditsProduct`),children:(0,k.jsx)(N,{credits:d})}):null,f.length>0?(0,k.jsx)(M,{title:o(`about.creditsBuiltWith`),children:(0,k.jsx)(N,{credits:f})}):null,t===null?(0,k.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,k.jsx)(g,{})}):m.length>0?(0,k.jsx)(M,{title:o(`about.creditsDeps`),hint:s?void 0:o(`about.creditsDepsHint`),children:m.map(e=>(0,k.jsx)(P,{label:e.label,packages:e.packages},e.id))}):null,t!==null&&h?(0,k.jsx)(p,{children:o(`about.noMatches`)}):null]})}var I=[`new`,`earlier`,`credits`],L=e=>o(e===`new`?`about.tab.new`:e===`earlier`?`about.tab.earlier`:`about.credits`),R=e=>e===1?o(`about.change`):o(`about.changes`,{n:e});function z({open:e,onClose:t,me:n}){let i=n?.mode===`local`,{data:a,latest:l}=v(i&&e),[u,p]=(0,E.useState)(null),[D,O]=(0,E.useState)(`new`),A=x(I.indexOf(D)),j=a?.newer&&l?l:y;(0,E.useEffect)(()=>{if(!e)return;let t=!1;return p(null),C(j===`0.4.0`?void 0:j).then(e=>{t||p(e)}),()=>{t=!0}},[e,j]);let M=u?.find(e=>e.version===`v${j}`)??u?.[0]??null,N=u?.filter(e=>e!==M)??[],P=i?a?.kind??null:`cloud`;return(0,k.jsxs)(m,{open:e,onClose:t,wide:!0,height:`tall`,children:[(0,k.jsx)(`div`,{className:`-mt-2 -mr-2 sticky top-0 z-10 flex h-0 justify-end`,children:(0,k.jsx)(d,{label:o(`common.close`),onClick:t,children:(0,k.jsx)(c,{className:`size-4`})})}),(0,k.jsxs)(`div`,{className:`flex flex-col items-center pt-4 text-center`,children:[(0,k.jsx)(r,{size:96}),(0,k.jsxs)(`div`,{className:`mt-4 font-display font-semibold text-[1.5rem] tracking-tight`,children:[`engenty`,(0,k.jsx)(`span`,{className:`text-ember`,children:`.`}),(0,k.jsx)(`span`,{className:`ml-1.5 font-normal text-ink-3`,children:`wizards`})]}),(0,k.jsxs)(`div`,{className:`mt-1 text-[0.9375rem] text-ink-3 tabular-nums`,children:[o(`about.version`,{v:y}),P?` · ${o(`about.kind.${P}`)}`:``]})]}),i?(0,k.jsx)(`div`,{className:`mt-5`,children:(0,k.jsx)(_,{enabled:e})}):null,(0,k.jsx)(`div`,{className:`mt-6 flex justify-center`,children:(0,k.jsx)(h,{value:D,onChange:O,options:I.map(e=>({id:e,label:L(e)})),label:o(`about.title`)})}),(0,k.jsxs)(`div`,{className:s(`mt-5`,b(A)),children:[D===`new`?u===null?(0,k.jsx)(`div`,{className:`flex justify-center py-6 text-ink-3`,children:(0,k.jsx)(g,{})}):M?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:[T(M),(0,k.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] text-ink-3 tabular-nums`,children:w(M)})]}),(0,k.jsx)(`div`,{className:`mt-3`,children:(0,k.jsx)(S,{release:M})})]}):(0,k.jsx)(`p`,{className:`text-[0.875rem] text-ink-3`,children:o(`about.changelogEmpty`)}):null,D===`earlier`?(0,k.jsx)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:N.map(e=>(0,k.jsxs)(`details`,{className:`group/r py-2`,children:[(0,k.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-baseline gap-3 text-[0.875rem] [&::-webkit-details-marker]:hidden`,children:[(0,k.jsx)(f,{className:`size-3.5 shrink-0 self-center text-ink-4 transition group-open/r:rotate-90`}),(0,k.jsx)(`span`,{className:`font-medium text-ink tabular-nums`,children:T(e)}),(0,k.jsx)(`span`,{className:`text-[0.8125rem] text-ink-3 tabular-nums`,children:w(e)}),(0,k.jsx)(`span`,{className:`ml-auto text-[0.8125rem] text-ink-4`,children:R(e.commits.length)})]}),(0,k.jsx)(`div`,{className:`mt-2 pl-6`,children:(0,k.jsx)(S,{release:e})})]},e.version??`unreleased`))}):null,D===`credits`?(0,k.jsx)(F,{active:!0}):null]},D)]})}export{z as AboutDialog};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{t as r}from"./preload-helper-CNEI7N0N.js";import{At as i,Et as a,gt as o,mt as s,pt as c,xt as l}from"./ui-DrjXmHdO.js";var u=e(t(),1),d=e(n(),1);function f(e){switch(e.group){case`Added`:return{label:`NEW`,dot:`bg-moss`};case`Fixed`:return{label:`FIXED`,dot:`bg-amber`};case`Changed`:return{label:`CHANGED`,dot:`bg-cobalt`};case`Performance`:return{label:`PERFORMANCE`,dot:`bg-ember`};case`Deploy`:return{label:`DEPLOY`,dot:`bg-ink-4`};case`Docs`:return{label:`DOCS`,dot:`bg-ink-4`};default:return{label:`OTHER`,dot:`bg-ink-4`}}}var p=e=>e.version?e.version.replace(/^v/,``):i(`about.unreleased`),m=e=>e.timestamp?new Date(e.timestamp*1e3).toISOString().slice(0,10):``,h=e=>e.charAt(0).toUpperCase()+e.slice(1);function g(e,t){let n=t.trim().toLowerCase();if(!n)return e;let r=[];for(let t of e){if(`${p(t)} ${m(t)}`.toLowerCase().includes(n)){r.push(t);continue}let e=t.commits.filter(e=>`${f(e).label} ${e.scope??``} ${e.message}`.toLowerCase().includes(n));e.length>0&&r.push({...t,commits:e})}return r}async function _(e){if(e)try{let t=await fetch(`https://raw.githubusercontent.com/engenty/engenty-wizards/v${e}/apps/web/src/about/changelog.json`,{signal:AbortSignal.timeout(5e3)});if(t.ok)return await t.json()}catch{}return(await r(async()=>{let{default:e}=await import(`./changelog-wZI-UaUi.js`);return{default:e}},[])).default}function v({release:e}){return(0,d.jsx)(`ul`,{className:`flex flex-col gap-2`,children:e.commits.map(e=>{let t=f(e);return(0,d.jsxs)(`li`,{className:`flex items-start gap-2.5 text-[0.875rem]`,children:[(0,d.jsx)(`span`,{className:a(`mt-[7px] size-1.5 shrink-0 rounded-full`,t.dot)}),(0,d.jsxs)(`span`,{className:`min-w-0 text-ink-2`,children:[(0,d.jsxs)(`span`,{className:`font-semibold text-[0.75rem] text-ink tracking-wide`,children:[t.label,e.scope?` [${e.scope}]`:``]}),` `,h(e.message),e.breaking?(0,d.jsx)(`span`,{className:`ml-1.5 rounded-full bg-rose-tint px-1.5 py-0.5 font-medium text-[0.75rem] text-rose`,children:i(`about.breaking`)}):null]})]},e.id)})})}function y({open:e,onClose:t,version:n}){let[r,a]=(0,u.useState)(null),[f,h]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||r)return;let t=!1;return _(n).then(e=>{t||a(e)}),()=>{t=!0}},[e,r,n]),(0,u.useEffect)(()=>{e||h(``)},[e]);let y=r?g(r,f):[];return(0,d.jsxs)(c,{open:e,onClose:t,title:i(`about.changelog`),wide:!0,height:`tall`,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:i(`about.changelogHint`)}),r===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(l,{})}):r.length===0?(0,d.jsx)(s,{children:i(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(o,{type:`search`,value:f,placeholder:i(`about.search`),onChange:e=>h(e.target.value)}),y.length===0?(0,d.jsx)(s,{children:i(`about.noMatches`)}):null,y.map(e=>(0,d.jsxs)(`section`,{className:`mt-6`,children:[(0,d.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:[p(e),(0,d.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] text-ink-3 tabular-nums`,children:m(e)})]}),(0,d.jsx)(`div`,{className:`mt-3`,children:(0,d.jsx)(v,{release:e})})]},e.version??`unreleased`))]})]})}export{y as ChangelogDialog,v as ReleaseNotes,_ as loadReleases,m as releaseDate,p as releaseLabel};
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{t as r}from"./preload-helper-CNEI7N0N.js";import{At as i,Et as a,gt as o,mt as s,pt as c,xt as l}from"./ui-D2SqIZeQ.js";var u=e(t(),1),d=e(n(),1);function f(e){switch(e.group){case`Added`:return{label:`NEW`,dot:`bg-moss`};case`Fixed`:return{label:`FIXED`,dot:`bg-amber`};case`Changed`:return{label:`CHANGED`,dot:`bg-cobalt`};case`Performance`:return{label:`PERFORMANCE`,dot:`bg-ember`};case`Deploy`:return{label:`DEPLOY`,dot:`bg-ink-4`};case`Docs`:return{label:`DOCS`,dot:`bg-ink-4`};default:return{label:`OTHER`,dot:`bg-ink-4`}}}var p=e=>e.version?e.version.replace(/^v/,``):i(`about.unreleased`),m=e=>e.timestamp?new Date(e.timestamp*1e3).toISOString().slice(0,10):``,h=e=>e.charAt(0).toUpperCase()+e.slice(1);function g(e,t){let n=t.trim().toLowerCase();if(!n)return e;let r=[];for(let t of e){if(`${p(t)} ${m(t)}`.toLowerCase().includes(n)){r.push(t);continue}let e=t.commits.filter(e=>`${f(e).label} ${e.scope??``} ${e.message}`.toLowerCase().includes(n));e.length>0&&r.push({...t,commits:e})}return r}async function _(e){if(e)try{let t=await fetch(`https://raw.githubusercontent.com/engenty/engenty-wizards/v${e}/apps/web/src/about/changelog.json`,{signal:AbortSignal.timeout(5e3)});if(t.ok)return await t.json()}catch{}return(await r(async()=>{let{default:e}=await import(`./changelog-DYZC2E6q.js`);return{default:e}},[])).default}function v({release:e}){return(0,d.jsx)(`ul`,{className:`flex flex-col gap-2`,children:e.commits.map(e=>{let t=f(e);return(0,d.jsxs)(`li`,{className:`flex items-start gap-2.5 text-[0.875rem]`,children:[(0,d.jsx)(`span`,{className:a(`mt-[7px] size-1.5 shrink-0 rounded-full`,t.dot)}),(0,d.jsxs)(`span`,{className:`min-w-0 text-ink-2`,children:[(0,d.jsxs)(`span`,{className:`font-semibold text-[0.75rem] text-ink tracking-wide`,children:[t.label,e.scope?` [${e.scope}]`:``]}),` `,h(e.message),e.breaking?(0,d.jsx)(`span`,{className:`ml-1.5 rounded-full bg-rose-tint px-1.5 py-0.5 font-medium text-[0.75rem] text-rose`,children:i(`about.breaking`)}):null]})]},e.id)})})}function y({open:e,onClose:t,version:n}){let[r,a]=(0,u.useState)(null),[f,h]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||r)return;let t=!1;return _(n).then(e=>{t||a(e)}),()=>{t=!0}},[e,r,n]),(0,u.useEffect)(()=>{e||h(``)},[e]);let y=r?g(r,f):[];return(0,d.jsxs)(c,{open:e,onClose:t,title:i(`about.changelog`),wide:!0,height:`tall`,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:i(`about.changelogHint`)}),r===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(l,{})}):r.length===0?(0,d.jsx)(s,{children:i(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(o,{type:`search`,value:f,placeholder:i(`about.search`),onChange:e=>h(e.target.value)}),y.length===0?(0,d.jsx)(s,{children:i(`about.noMatches`)}):null,y.map(e=>(0,d.jsxs)(`section`,{className:`mt-6`,children:[(0,d.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:[p(e),(0,d.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] text-ink-3 tabular-nums`,children:m(e)})]}),(0,d.jsx)(`div`,{className:`mt-3`,children:(0,d.jsx)(v,{release:e})})]},e.version??`unreleased`))]})]})}export{y as ChangelogDialog,v as ReleaseNotes,_ as loadReleases,m as releaseDate,p as releaseLabel};
@@ -1,4 +1,4 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{A as r,At as i,B as a,C as o,D as s,Dt as c,Et as l,Ft as u,Gt as d,Ht as f,It as p,Lt as m,M as h,N as g,Nt as _,Ot as v,P as y,Rt as b,S as x,Tt as S,Y as C,at as w,c as T,ht as E,it as D,j as O,k,ln as A,ot as j,pn as M,qt as N,rt as P,sn as F,tt as I,u as L,vt as ee,x as R,xt as z,y as B}from"./ui-DrjXmHdO.js";import{t as te}from"./phone-XIVIe17d.js";import{$t as ne,Ht as re,It as ie,_n as ae,bt as oe,t as se,tn as ce,xt as le,yt as ue}from"./index-DnQgOKOQ.js";import{n as de}from"./RunnerView-ii-PP5c-.js";var fe={name:`hand`,size:24,node:[[`path`,{d:`M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2`,key:`1fvzgz`}],[`path`,{d:`M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2`,key:`1kc0my`}],[`path`,{d:`M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8`,key:`10h0bg`}],[`path`,{d:`M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15`,key:`1s1gnw`}]]};fe.node;var pe=M(fe),me={name:`undo-2`,size:24,node:[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]};me.node;var he=M(me),ge={name:`video-off`,size:24,node:[[`path`,{d:`M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196`,key:`w8jjjt`}],[`path`,{d:`M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2`,key:`1xawa7`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]};ge.node;var V=M(ge),_e={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`}]]};_e.node;var ve=M(_e),ye=ae(),H=e(t(),1),U=e(n(),1),be=typeof window<`u`&&window.matchMedia(`(pointer: coarse)`).matches;function xe({since:e}){let[t,n]=(0,H.useState)(Date.now());if((0,H.useEffect)(()=>{if(!e)return;let t=setInterval(()=>n(Date.now()),1e3);return()=>clearInterval(t)},[e]),!e)return null;let r=Math.max(0,Math.floor((t-e)/1e3)),i=String(Math.floor(r/60)).padStart(2,`0`),a=String(r%60).padStart(2,`0`);return(0,U.jsxs)(`span`,{className:`font-mono text-[0.8125rem] text-white/60 tabular-nums`,children:[i,`:`,a]})}function W({label:e,on:t,danger:n,busy:r,onClick:i,children:a}){return(0,U.jsx)(`button`,{type:`button`,"aria-label":e,title:e,"aria-pressed":t,disabled:r,onClick:i,className:l(`flex size-12 items-center justify-center rounded-full transition disabled:opacity-50`,n?`bg-rose text-white hover:brightness-110`:t===!1?`bg-white text-neutral-900 hover:bg-white/90`:`bg-white/15 text-white hover:bg-white/25`),children:r?(0,U.jsx)(z,{className:`size-5`}):a})}function Se({voice:e}){let t=(0,H.useRef)(null),{captions:n}=e;return(0,H.useEffect)(()=>{n.length&&t.current?.scrollIntoView({block:`end`})},[n]),n.length?(0,U.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 sm:px-5`,children:(0,U.jsxs)(`ol`,{className:`mx-auto flex max-w-[720px] flex-col gap-2 py-2`,children:[n.map(e=>(0,U.jsx)(`li`,{className:l(`text-[0.9375rem] leading-snug`,e.who===`bot`?`text-white/95`:`text-right text-white/50`),children:e.text},e.id)),(0,U.jsx)(`div`,{ref:t})]})}):null}function Ce({voice:e,view:t,video:n,className:r}){let a=e.state===`live`,o=e.state===`connecting`,[s,c]=(0,H.useState)(null),[d,f]=(0,H.useState)(!1);(0,H.useEffect)(()=>{c(a?Date.now():null)},[a]);let p=async()=>{f(!1),await e.start(),n&&await e.startCamera()},m=()=>{e.stop(),f(!0)},h=n||e.camera,g=[...e.captions].reverse().find(e=>e.who===`bot`),v=[...e.captions].reverse().find(e=>e.who===`me`),y=e.speaking?i(`talk.speaking`):e.listening?i(`talk.listening`):a?i(`talk.live`):o?i(`talk.connecting`):d?i(`video.ended`):``;return(0,U.jsxs)(`section`,{className:l(`relative flex min-h-0 flex-col bg-neutral-950 text-white`,`safe-top`,r),children:[(0,U.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 px-4 sm:px-5`,children:[(0,U.jsx)(`div`,{className:`min-w-0 flex-1 truncate font-display font-semibold text-[1rem] tracking-tight`,children:t?.wizard.title??``}),y?(0,U.jsxs)(`span`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-white/70`,children:[a?(0,U.jsx)(`span`,{className:l(`size-2 rounded-full`,e.speaking?`animate-pulse-dot bg-emerald-400`:`bg-rose`)}):null,y]}):null,(0,U.jsx)(xe,{since:s})]}),(0,U.jsxs)(`div`,{className:l(`grid min-h-0 gap-2 px-3 pb-2 sm:px-4`,h?`flex-1 grid-cols-1 sm:grid-cols-2`:`shrink-0 grid-cols-1`,!h&&a&&e.captions.length?`h-[38%]`:h?``:`flex-1`),children:[(0,U.jsxs)(`div`,{className:l(`relative min-h-0 overflow-hidden rounded-2xl bg-neutral-900`,!h&&`hidden`),children:[(0,U.jsx)(`video`,{ref:e.video,muted:!0,playsInline:!0,autoPlay:!0,className:l(`absolute inset-0 h-full w-full object-cover`,e.facing===`user`&&`-scale-x-100`,e.camera?`block`:`hidden`)}),e.camera?null:(0,U.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/50`,children:[(0,U.jsx)(V,{className:`size-8`}),(0,U.jsx)(`span`,{className:`text-[0.8125rem]`,children:i(`video.cameraOff`)})]}),(0,U.jsxs)(`span`,{className:`absolute bottom-2 left-3 rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:[i(`video.you`),e.muted?(0,U.jsx)(ce,{className:`ml-1.5 inline size-3`}):null]})]}),(0,U.jsxs)(`div`,{className:l(`relative flex min-h-0 items-center justify-center overflow-hidden rounded-2xl transition-shadow`,h?`bg-neutral-900`:`bg-transparent`,h&&e.speaking&&`ring-2 ring-emerald-400/70`),children:[(0,U.jsx)(`div`,{className:l(`rounded-full transition-shadow duration-500`,!h&&e.listening&&`shadow-[0_0_80px_20px_rgba(244,63,94,0.25)]`,!h&&e.speaking&&`shadow-[0_0_80px_20px_rgba(52,211,153,0.3)]`,e.speaking&&`animate-breathe`),children:(0,U.jsx)(ie,{kind:t?.wizard.avatar??`round`,size:h?140:200,fluffy:!0,interactive:!1})}),h?(0,U.jsx)(`span`,{className:`absolute bottom-2 left-3 max-w-[85%] truncate rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:t?.wizard.title??``}):null]})]}),a&&!h?(0,U.jsx)(Se,{voice:e}):a&&(g||v)?(0,U.jsx)(`div`,{className:`shrink-0 px-4 pb-2 sm:px-5`,children:(0,U.jsxs)(`div`,{className:`mx-auto max-w-[720px] space-y-1 text-center`,children:[v?(0,U.jsx)(`p`,{className:`line-clamp-1 text-[0.8125rem] text-white/50`,children:v.text}):null,g?(0,U.jsx)(`p`,{className:`line-clamp-3 text-[0.9375rem] text-white/95 leading-snug`,children:g.text}):null]})}):null,e.error?(0,U.jsx)(`p`,{className:`shrink-0 px-5 pb-2 text-center text-[0.8125rem] text-rose`,children:e.error}):null,(0,U.jsx)(`div`,{className:`flex shrink-0 items-center justify-center gap-3 px-4 pt-1 pb-4`,children:a?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(W,{label:i(e.muted?`video.unmute`:`video.mute`),on:!e.muted,onClick:e.toggleMute,children:e.muted?(0,U.jsx)(ce,{className:`size-5`}):(0,U.jsx)(N,{className:`size-5`})}),(0,U.jsx)(W,{label:i(e.camera?`talk.cameraOff`:`talk.camera`),on:e.camera,onClick:()=>e.camera?e.stopCamera():void e.startCamera(),children:e.camera?(0,U.jsx)(_,{className:`size-5`}):(0,U.jsx)(V,{className:`size-5`})}),e.camera&&be?(0,U.jsx)(W,{label:i(`video.flip`),onClick:()=>void e.flipCamera(),children:(0,U.jsx)(u,{className:`size-5`})}):null,(0,U.jsx)(W,{label:i(`video.leave`),danger:!0,onClick:m,children:(0,U.jsx)(ne,{className:`size-5`})})]}):(0,U.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[(0,U.jsxs)(`button`,{type:`button`,disabled:o||!t?.talk,onClick:()=>void p(),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,U.jsx)(z,{className:`size-4`}):n?(0,U.jsx)(_,{className:`size-5`}):(0,U.jsx)(N,{className:`size-5`}),i(d?`video.rejoin`:n?`video.join`:`talk.start`)]}),!d&&!e.error?(0,U.jsx)(`p`,{className:`max-w-sm text-center text-[0.75rem] text-white/50`,children:i(n?`video.hint`:`talk.joinHint`)}):null]})})]})}var we=e=>a[e.kind]!==`device`,Te=1024,Ee=4e3;function De(e,t){return e?e.length>t?`${e.slice(0,t)} …`:e:``}function Oe(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(`
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{A as r,At as i,B as a,C as o,D as s,Dt as c,Et as l,Ft as u,Gt as d,Ht as f,It as p,Lt as m,M as h,N as g,Nt as _,Ot as v,P as y,Rt as b,S as x,Tt as S,Y as C,at as w,c as T,ht as E,it as D,j as O,k,ln as A,ot as j,pn as M,qt as N,rt as P,sn as F,tt as I,u as L,vt as ee,x as R,xt as z,y as B}from"./ui-D2SqIZeQ.js";import{t as te}from"./phone-Bt1cyWpY.js";import{$t as ne,Ht as re,It as ie,_n as ae,bt as oe,t as se,tn as ce,xt as le,yt as ue}from"./index-BH0PYgov.js";import{n as de}from"./RunnerView-BPPmlv9z.js";var fe={name:`hand`,size:24,node:[[`path`,{d:`M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2`,key:`1fvzgz`}],[`path`,{d:`M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2`,key:`1kc0my`}],[`path`,{d:`M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8`,key:`10h0bg`}],[`path`,{d:`M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15`,key:`1s1gnw`}]]};fe.node;var pe=M(fe),me={name:`undo-2`,size:24,node:[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]};me.node;var he=M(me),ge={name:`video-off`,size:24,node:[[`path`,{d:`M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196`,key:`w8jjjt`}],[`path`,{d:`M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2`,key:`1xawa7`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]};ge.node;var V=M(ge),_e={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`}]]};_e.node;var ve=M(_e),ye=ae(),H=e(t(),1),U=e(n(),1),be=typeof window<`u`&&window.matchMedia(`(pointer: coarse)`).matches;function xe({since:e}){let[t,n]=(0,H.useState)(Date.now());if((0,H.useEffect)(()=>{if(!e)return;let t=setInterval(()=>n(Date.now()),1e3);return()=>clearInterval(t)},[e]),!e)return null;let r=Math.max(0,Math.floor((t-e)/1e3)),i=String(Math.floor(r/60)).padStart(2,`0`),a=String(r%60).padStart(2,`0`);return(0,U.jsxs)(`span`,{className:`font-mono text-[0.8125rem] text-white/60 tabular-nums`,children:[i,`:`,a]})}function W({label:e,on:t,danger:n,busy:r,onClick:i,children:a}){return(0,U.jsx)(`button`,{type:`button`,"aria-label":e,title:e,"aria-pressed":t,disabled:r,onClick:i,className:l(`flex size-12 items-center justify-center rounded-full transition disabled:opacity-50`,n?`bg-rose text-white hover:brightness-110`:t===!1?`bg-white text-neutral-900 hover:bg-white/90`:`bg-white/15 text-white hover:bg-white/25`),children:r?(0,U.jsx)(z,{className:`size-5`}):a})}function Se({voice:e}){let t=(0,H.useRef)(null),{captions:n}=e;return(0,H.useEffect)(()=>{n.length&&t.current?.scrollIntoView({block:`end`})},[n]),n.length?(0,U.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 sm:px-5`,children:(0,U.jsxs)(`ol`,{className:`mx-auto flex max-w-[720px] flex-col gap-2 py-2`,children:[n.map(e=>(0,U.jsx)(`li`,{className:l(`text-[0.9375rem] leading-snug`,e.who===`bot`?`text-white/95`:`text-right text-white/50`),children:e.text},e.id)),(0,U.jsx)(`div`,{ref:t})]})}):null}function Ce({voice:e,view:t,video:n,className:r}){let a=e.state===`live`,o=e.state===`connecting`,[s,c]=(0,H.useState)(null),[d,f]=(0,H.useState)(!1);(0,H.useEffect)(()=>{c(a?Date.now():null)},[a]);let p=async()=>{f(!1),await e.start(),n&&await e.startCamera()},m=()=>{e.stop(),f(!0)},h=n||e.camera,g=[...e.captions].reverse().find(e=>e.who===`bot`),v=[...e.captions].reverse().find(e=>e.who===`me`),y=e.speaking?i(`talk.speaking`):e.listening?i(`talk.listening`):a?i(`talk.live`):o?i(`talk.connecting`):d?i(`video.ended`):``;return(0,U.jsxs)(`section`,{className:l(`relative flex min-h-0 flex-col bg-neutral-950 text-white`,`safe-top`,r),children:[(0,U.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 px-4 sm:px-5`,children:[(0,U.jsx)(`div`,{className:`min-w-0 flex-1 truncate font-display font-semibold text-[1rem] tracking-tight`,children:t?.wizard.title??``}),y?(0,U.jsxs)(`span`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-white/70`,children:[a?(0,U.jsx)(`span`,{className:l(`size-2 rounded-full`,e.speaking?`animate-pulse-dot bg-emerald-400`:`bg-rose`)}):null,y]}):null,(0,U.jsx)(xe,{since:s})]}),(0,U.jsxs)(`div`,{className:l(`grid min-h-0 gap-2 px-3 pb-2 sm:px-4`,h?`flex-1 grid-cols-1 sm:grid-cols-2`:`shrink-0 grid-cols-1`,!h&&a&&e.captions.length?`h-[38%]`:h?``:`flex-1`),children:[(0,U.jsxs)(`div`,{className:l(`relative min-h-0 overflow-hidden rounded-2xl bg-neutral-900`,!h&&`hidden`),children:[(0,U.jsx)(`video`,{ref:e.video,muted:!0,playsInline:!0,autoPlay:!0,className:l(`absolute inset-0 h-full w-full object-cover`,e.facing===`user`&&`-scale-x-100`,e.camera?`block`:`hidden`)}),e.camera?null:(0,U.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/50`,children:[(0,U.jsx)(V,{className:`size-8`}),(0,U.jsx)(`span`,{className:`text-[0.8125rem]`,children:i(`video.cameraOff`)})]}),(0,U.jsxs)(`span`,{className:`absolute bottom-2 left-3 rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:[i(`video.you`),e.muted?(0,U.jsx)(ce,{className:`ml-1.5 inline size-3`}):null]})]}),(0,U.jsxs)(`div`,{className:l(`relative flex min-h-0 items-center justify-center overflow-hidden rounded-2xl transition-shadow`,h?`bg-neutral-900`:`bg-transparent`,h&&e.speaking&&`ring-2 ring-emerald-400/70`),children:[(0,U.jsx)(`div`,{className:l(`rounded-full transition-shadow duration-500`,!h&&e.listening&&`shadow-[0_0_80px_20px_rgba(244,63,94,0.25)]`,!h&&e.speaking&&`shadow-[0_0_80px_20px_rgba(52,211,153,0.3)]`,e.speaking&&`animate-breathe`),children:(0,U.jsx)(ie,{kind:t?.wizard.avatar??`round`,size:h?140:200,fluffy:!0,interactive:!1})}),h?(0,U.jsx)(`span`,{className:`absolute bottom-2 left-3 max-w-[85%] truncate rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:t?.wizard.title??``}):null]})]}),a&&!h?(0,U.jsx)(Se,{voice:e}):a&&(g||v)?(0,U.jsx)(`div`,{className:`shrink-0 px-4 pb-2 sm:px-5`,children:(0,U.jsxs)(`div`,{className:`mx-auto max-w-[720px] space-y-1 text-center`,children:[v?(0,U.jsx)(`p`,{className:`line-clamp-1 text-[0.8125rem] text-white/50`,children:v.text}):null,g?(0,U.jsx)(`p`,{className:`line-clamp-3 text-[0.9375rem] text-white/95 leading-snug`,children:g.text}):null]})}):null,e.error?(0,U.jsx)(`p`,{className:`shrink-0 px-5 pb-2 text-center text-[0.8125rem] text-rose`,children:e.error}):null,(0,U.jsx)(`div`,{className:`flex shrink-0 items-center justify-center gap-3 px-4 pt-1 pb-4`,children:a?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(W,{label:i(e.muted?`video.unmute`:`video.mute`),on:!e.muted,onClick:e.toggleMute,children:e.muted?(0,U.jsx)(ce,{className:`size-5`}):(0,U.jsx)(N,{className:`size-5`})}),(0,U.jsx)(W,{label:i(e.camera?`talk.cameraOff`:`talk.camera`),on:e.camera,onClick:()=>e.camera?e.stopCamera():void e.startCamera(),children:e.camera?(0,U.jsx)(_,{className:`size-5`}):(0,U.jsx)(V,{className:`size-5`})}),e.camera&&be?(0,U.jsx)(W,{label:i(`video.flip`),onClick:()=>void e.flipCamera(),children:(0,U.jsx)(u,{className:`size-5`})}):null,(0,U.jsx)(W,{label:i(`video.leave`),danger:!0,onClick:m,children:(0,U.jsx)(ne,{className:`size-5`})})]}):(0,U.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[(0,U.jsxs)(`button`,{type:`button`,disabled:o||!t?.talk,onClick:()=>void p(),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,U.jsx)(z,{className:`size-4`}):n?(0,U.jsx)(_,{className:`size-5`}):(0,U.jsx)(N,{className:`size-5`}),i(d?`video.rejoin`:n?`video.join`:`talk.start`)]}),!d&&!e.error?(0,U.jsx)(`p`,{className:`max-w-sm text-center text-[0.75rem] text-white/50`,children:i(n?`video.hint`:`talk.joinHint`)}):null]})})]})}var we=e=>a[e.kind]!==`device`,Te=1024,Ee=4e3;function De(e,t){return e?e.length>t?`${e.slice(0,t)} …`:e:``}function Oe(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
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: ${c(t)}`),r.join(`
3
3
  `)}if(e.status===`done`){r.push(`done. made:`);for(let{step:t,output:n}of e.shown)r.push(`- ${t.title}: ${De(n?.text,400)||`(a file, on the screen)`}`);return r.join(`
4
4
  `)}if(e.status===`failed`)return r.push(`failed: ${e.error??``}; go_back or the person retries on the screen`),r.join(`