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
@@ -1,9 +1,11 @@
1
1
  import { TableColumnValueError, tableColumnsSchema, } from "@engenty-wizards/shared/engenty/data-tables";
2
+ import { bilingual } from "@engenty-wizards/shared/run";
2
3
  import { editCells, SPACE_DATA_LIMITS, } from "@engenty-wizards/shared/space-data";
3
4
  import { rowKey } from "@engenty-wizards/shared/store";
4
5
  import { and, asc, count, desc, eq, inArray, isNotNull, isNull, max } from "drizzle-orm";
5
6
  import { nanoid } from "nanoid";
6
7
  import { db, schema } from "../db/client.js";
8
+ import { saidOf } from "../model-errors.js";
7
9
  import { currentTenant } from "../tenants/tenant.js";
8
10
  import { projectWritable, requireWritableProject } from "./access.js";
9
11
  import { notFound, ServiceError } from "./errors.js";
@@ -21,20 +23,20 @@ async function ownerOf(projectId, wizardId) {
21
23
  columns: { id: true },
22
24
  });
23
25
  if (!w) {
24
- throw new ServiceError("invalid", "Diesen Wizard gibt es im Space nicht.");
26
+ throw new ServiceError("invalid", bilingual("Diesen Wizard gibt es im Space nicht.", "There is no such wizard in the space."));
25
27
  }
26
28
  return w.id;
27
29
  }
28
30
  function cellError(err) {
29
31
  if (err instanceof TableColumnValueError) {
30
- throw new ServiceError("invalid", err.message, { column: err.columnId });
32
+ throw new ServiceError("invalid", saidOf(err), { column: err.columnId });
31
33
  }
32
34
  throw err;
33
35
  }
34
36
  export function checkColumns(columns) {
35
37
  const parsed = tableColumnsSchema.safeParse(columns);
36
38
  if (!parsed.success) {
37
- throw new ServiceError("invalid", parsed.error.issues[0]?.message ?? "Ungültige Spalten.");
39
+ throw new ServiceError("invalid", parsed.error.issues[0]?.message ?? bilingual("Ungültige Spalten.", "Invalid columns."));
38
40
  }
39
41
  return parsed.data;
40
42
  }
@@ -102,10 +104,11 @@ async function tableCount(projectId) {
102
104
  .from(schema.spaceTable)
103
105
  .where(eq(schema.spaceTable.projectId, projectId));
104
106
  if (n >= SPACE_DATA_LIMITS.tables) {
105
- throw new ServiceError("refused", `Ein Space hat höchstens ${SPACE_DATA_LIMITS.tables} Tabellen.`);
107
+ throw new ServiceError("refused", bilingual(`Ein Space hat höchstens ${SPACE_DATA_LIMITS.tables} Tabellen.`, `A space has at most ${SPACE_DATA_LIMITS.tables} tables.`));
106
108
  }
107
109
  }
108
- export async function createTable(userId, projectId, input) {
110
+ export async function createTable(userId, projectId, input, lang = "en") {
111
+ const de = lang === "de";
109
112
  const project = await ownedProject(userId, projectId);
110
113
  await requireWritableProject(project.id);
111
114
  await tableCount(project.id);
@@ -113,10 +116,10 @@ export async function createTable(userId, projectId, input) {
113
116
  ? checkColumns(input.columns)
114
117
  : input.format === "faq"
115
118
  ? [
116
- { id: "frage", name: "Frage", type: "text" },
119
+ { id: "question", name: de ? "Frage" : "Question", type: "text" },
117
120
  {
118
- id: "antwort",
119
- name: "Antwort",
121
+ id: "answer",
122
+ name: de ? "Antwort" : "Answer",
120
123
  type: "text",
121
124
  format: { style: "multiline" },
122
125
  },
@@ -124,7 +127,7 @@ export async function createTable(userId, projectId, input) {
124
127
  : [{ id: "name", name: "Name", type: "text" }];
125
128
  const id = nanoid(12);
126
129
  const wizardId = await ownerOf(project.id, input.wizardId);
127
- const title = input.title.trim() || "Tabelle";
130
+ const title = input.title.trim() || (de ? "Tabelle" : "Table");
128
131
  await db.insert(schema.spaceTable).values({
129
132
  id,
130
133
  tenantId: currentTenant(),
@@ -184,7 +187,7 @@ export async function getTable(userId, tableId) {
184
187
  export async function updateTable(_userId, tableId, patch) {
185
188
  const table = await writableTable(tableId);
186
189
  if (table.list && (patch.columns !== undefined || patch.wizardId !== undefined)) {
187
- throw new ServiceError("refused", "Diese Tabelle gehört zu einer Liste des Wizards: ihre Spalten kommen aus dem Wizard.");
190
+ throw new ServiceError("refused", bilingual("Diese Tabelle gehört zu einer Liste des Wizards: ihre Spalten kommen aus dem Wizard.", "This table belongs to one of the wizard's lists: its columns come from the wizard."));
188
191
  }
189
192
  const title = patch.title !== undefined ? patch.title.trim() || table.title : table.title;
190
193
  const wizardId = patch.wizardId !== undefined ? await ownerOf(table.projectId, patch.wizardId) : table.wizardId;
@@ -247,7 +250,7 @@ async function refuseClash(tableId, key, rowId) {
247
250
  columns: { id: true },
248
251
  });
249
252
  if (other && other.id !== rowId) {
250
- throw new ServiceError("invalid", "Diesen Eintrag gibt es schon.");
253
+ throw new ServiceError("invalid", bilingual("Diesen Eintrag gibt es schon.", "This entry already exists."));
251
254
  }
252
255
  }
253
256
  /** After a row of a table of Wissen changed: its Kategorien from its columns, its unit. */
@@ -266,7 +269,7 @@ export async function addTableRow(_userId, tableId, cells = {}) {
266
269
  .from(schema.spaceTableRow)
267
270
  .where(eq(schema.spaceTableRow.tableId, table.id));
268
271
  if (n >= SPACE_DATA_LIMITS.rowsPerTable) {
269
- throw new ServiceError("refused", `Eine Tabelle hat höchstens ${SPACE_DATA_LIMITS.rowsPerTable} Zeilen.`);
272
+ throw new ServiceError("refused", bilingual(`Eine Tabelle hat höchstens ${SPACE_DATA_LIMITS.rowsPerTable} Zeilen.`, `A table has at most ${SPACE_DATA_LIMITS.rowsPerTable} rows.`));
270
273
  }
271
274
  let value;
272
275
  try {
@@ -331,7 +334,7 @@ async function pageRow(pageId) {
331
334
  }
332
335
  function checkMarkdown(markdown) {
333
336
  if (markdown.length > SPACE_DATA_LIMITS.pageChars) {
334
- throw new ServiceError("refused", `Eine Seite hat höchstens ${SPACE_DATA_LIMITS.pageChars.toLocaleString("de")} Zeichen.`);
337
+ throw new ServiceError("refused", bilingual(`Eine Seite hat höchstens ${SPACE_DATA_LIMITS.pageChars.toLocaleString("de")} Zeichen.`, `A page has at most ${SPACE_DATA_LIMITS.pageChars.toLocaleString("en")} characters.`));
335
338
  }
336
339
  return markdown;
337
340
  }
@@ -341,7 +344,7 @@ async function pageCount(projectId, more = 1) {
341
344
  .from(schema.spacePage)
342
345
  .where(eq(schema.spacePage.projectId, projectId));
343
346
  if (n + more > SPACE_DATA_LIMITS.pages) {
344
- throw new ServiceError("refused", `Ein Space hat höchstens ${SPACE_DATA_LIMITS.pages} Seiten.`);
347
+ throw new ServiceError("refused", bilingual(`Ein Space hat höchstens ${SPACE_DATA_LIMITS.pages} Seiten.`, `A space has at most ${SPACE_DATA_LIMITS.pages} pages.`));
345
348
  }
346
349
  }
347
350
  /** A page of the space's own that a sub-page may stand under: never one of its own sub-pages. */
@@ -354,11 +357,11 @@ async function parentOf(projectId, parentId, pageId) {
354
357
  columns: { id: true, wizardId: true, parentId: true },
355
358
  });
356
359
  if (!parent || parent.wizardId) {
357
- throw new ServiceError("invalid", "Unter diese Seite kann keine Seite.");
360
+ throw new ServiceError("invalid", bilingual("Unter diese Seite kann keine Seite.", "No page can go under this page."));
358
361
  }
359
362
  for (let at = parent.id; at && pageId;) {
360
363
  if (at === pageId) {
361
- throw new ServiceError("invalid", "Eine Seite kann nicht unter sich selbst stehen.");
364
+ throw new ServiceError("invalid", bilingual("Eine Seite kann nicht unter sich selbst stehen.", "A page cannot stand under itself."));
362
365
  }
363
366
  const up = await db.query.spacePage.findFirst({
364
367
  where: eq(schema.spacePage.id, at),
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { tableColumnsSchema } from "@engenty-wizards/shared/engenty/data-tables";
3
3
  import { CATEGORY_TYPES } from "@engenty-wizards/shared/knowledge";
4
4
  import { PROJECT_LIMITS } from "@engenty-wizards/shared/projects";
5
+ import { bilingual } from "@engenty-wizards/shared/run";
5
6
  import { SPACE_DATA_LIMITS } from "@engenty-wizards/shared/space-data";
6
7
  import { WORKSPACE_LIMITS } from "@engenty-wizards/shared/workspace";
7
8
  import { and, count, eq, inArray, isNull, notInArray, sql } from "drizzle-orm";
@@ -150,8 +151,8 @@ async function requireRoom(spaceId) {
150
151
  const limit = await projectLimit();
151
152
  if (others.length >= limit) {
152
153
  throw new ServiceError("refused", limit === 1
153
- ? "Dieses Konto hat hier schon ein Projekt."
154
- : `Dieses Konto hat hier schon ${limit} Projekte.`, {
154
+ ? bilingual("Dieses Konto hat hier schon ein Projekt.", "This account already has a project here.")
155
+ : bilingual(`Dieses Konto hat hier schon ${limit} Projekte.`, `This account already has ${limit} projects here.`), {
155
156
  reason: "space_limit",
156
157
  limit,
157
158
  spaces: others.filter((p) => p.origin === "local").map((p) => ({ id: p.id, name: p.name })),
@@ -165,7 +166,7 @@ async function requireWizardRoom(spaceId) {
165
166
  .from(schema.wizard)
166
167
  .where(eq(schema.wizard.projectId, spaceId));
167
168
  if ((row?.n ?? 0) >= env.limits.syncedWizards) {
168
- throw new ServiceError("refused", `Hier haben höchstens ${env.limits.syncedWizards} veröffentlichte Wizards Platz.`, { reason: "wizard_limit", limit: env.limits.syncedWizards });
169
+ throw new ServiceError("refused", bilingual(`Hier haben höchstens ${env.limits.syncedWizards} veröffentlichte Wizards Platz.`, `There is room for at most ${env.limits.syncedWizards} published wizards here.`), { reason: "wizard_limit", limit: env.limits.syncedWizards });
169
170
  }
170
171
  }
171
172
  const hashOf = (data) => createHash("sha256").update(data).digest("hex");
@@ -199,7 +200,7 @@ async function syncLogo(projectId, logo) {
199
200
  async function syncSpace(spaceId, space) {
200
201
  const existing = await syncedProject(spaceId);
201
202
  if (existing && existing.origin !== "local") {
202
- throw new ServiceError("refused", "Ein Projekt mit dieser Kennung wurde hier angelegt.", {
203
+ throw new ServiceError("refused", bilingual("Ein Projekt mit dieser Kennung wurde hier angelegt.", "A project with this id was created here."), {
203
204
  reason: "id_taken",
204
205
  });
205
206
  }
@@ -250,7 +251,7 @@ export async function syncWizard(rawSpaceId, rawWizardId, input) {
250
251
  where: and(eq(schema.wizard.id, wizardId), eq(schema.wizard.tenantId, currentTenant())),
251
252
  });
252
253
  if (existing && existing.projectId !== spaceId) {
253
- throw new ServiceError("refused", "Ein Wizard mit dieser Kennung gehört hier woanders hin.", {
254
+ throw new ServiceError("refused", bilingual("Ein Wizard mit dieser Kennung gehört hier woanders hin.", "A wizard with this id belongs elsewhere here."), {
254
255
  reason: "id_taken",
255
256
  });
256
257
  }
@@ -506,7 +507,7 @@ export async function syncSpaceData(rawSpaceId, input) {
506
507
  : [],
507
508
  ]);
508
509
  if ([...tablesHere, ...pagesHere].some((x) => x.projectId !== spaceId || x.wizardId !== null)) {
509
- throw new ServiceError("refused", "Eine Kennung ist hier schon vergeben.", {
510
+ throw new ServiceError("refused", bilingual("Eine Kennung ist hier schon vergeben.", "An id is already taken here."), {
510
511
  reason: "id_taken",
511
512
  });
512
513
  }
@@ -584,7 +585,7 @@ async function syncCategories(spaceId, categories, assignments) {
584
585
  })
585
586
  : [];
586
587
  if (taken.some((c) => c.projectId !== spaceId)) {
587
- throw new ServiceError("refused", "Eine Kennung ist hier schon vergeben.", {
588
+ throw new ServiceError("refused", bilingual("Eine Kennung ist hier schon vergeben.", "An id is already taken here."), {
588
589
  reason: "id_taken",
589
590
  });
590
591
  }
@@ -1,11 +1,13 @@
1
1
  import { versionChanges } from "@engenty-wizards/shared/changes";
2
2
  import { pluginToolOf, shapeIssues, validateWizard, wizardSchema, } from "@engenty-wizards/shared/definition";
3
+ import { bilingual } from "@engenty-wizards/shared/run";
3
4
  import { and, desc, eq, sql } from "drizzle-orm";
4
5
  import { nanoid } from "nanoid";
5
6
  import { applyOps, OpError } from "../authoring/ops.js";
6
7
  import { listConnectors } from "../connectors/external.js";
7
8
  import { db, schema } from "../db/client.js";
8
9
  import { env } from "../env.js";
10
+ import { saidOf } from "../model-errors.js";
9
11
  import { pluginToolsOf } from "../plugins/registry.js";
10
12
  import { dropLinks, putLink } from "../tenants/control.js";
11
13
  import { currentTenant } from "../tenants/tenant.js";
@@ -17,21 +19,33 @@ import { forgetWizardLinks } from "./links.js";
17
19
  import { asLang, countInstall, marketplaceWizard } from "./marketplace.js";
18
20
  import { defaultProject, ownedProject } from "./projects.js";
19
21
  import { checkRunnerSettings } from "./runners.js";
20
- const BLANK = {
21
- version: 1,
22
- title: "Neuer Wizard",
23
- description: "",
24
- avatar: "round",
25
- steps: [
26
- {
27
- id: "start",
28
- type: "page",
29
- title: "Los geht's",
30
- fields: [{ id: "input", label: "Worum geht es?", kind: "textarea", required: true }],
31
- },
32
- { id: "done", type: "result", title: "Fertig", deliverables: [] },
33
- ],
34
- };
22
+ /** The wizard a new one starts as, in the language of whoever makes it. */
23
+ function blankWizard(lang) {
24
+ const de = lang === "de";
25
+ return {
26
+ version: 1,
27
+ title: de ? "Neuer Wizard" : "New wizard",
28
+ description: "",
29
+ avatar: "round",
30
+ lang,
31
+ steps: [
32
+ {
33
+ id: "start",
34
+ type: "page",
35
+ title: de ? "Los geht's" : "Let's start",
36
+ fields: [
37
+ {
38
+ id: "input",
39
+ label: de ? "Worum geht es?" : "What is it about?",
40
+ kind: "textarea",
41
+ required: true,
42
+ },
43
+ ],
44
+ },
45
+ { id: "done", type: "result", title: de ? "Fertig" : "Done", deliverables: [] },
46
+ ],
47
+ };
48
+ }
35
49
  export const studioUrl = (wizardId) => `${env.appUrl}/studio/edit/${wizardId}`;
36
50
  export const shareUrl = (token) => `${env.publicUrl}/w/${token}`;
37
51
  const newShareToken = () => nanoid(14);
@@ -227,9 +241,16 @@ export async function createWizard(userId, input, writer = { source: "studio" })
227
241
  if (input.starterId && !starter) {
228
242
  throw new ServiceError("invalid", `There is no starter "${input.starterId}".`);
229
243
  }
244
+ const maker = input.lang?.toLowerCase().startsWith("de") ? "de" : "en";
230
245
  const { draft, issues } = input.definition !== undefined
231
246
  ? parseDraft(input.definition)
232
- : { draft: starter?.definition ?? structuredClone(BLANK), issues: [] };
247
+ : starter
248
+ ? // A starter names the language it is written in, where its definition does not.
249
+ {
250
+ draft: { ...starter.definition, lang: starter.definition.lang ?? starter.language },
251
+ issues: [],
252
+ }
253
+ : { draft: blankWizard(maker), issues: [] };
233
254
  const fromStarter = input.definition === undefined ? starter : undefined;
234
255
  const id = nanoid(12);
235
256
  const shareToken = newShareToken();
@@ -287,7 +308,7 @@ export async function writeDraft(userId, wizardId, input, writer = { source: "st
287
308
  .returning({ revision: schema.wizard.revision });
288
309
  if (!row) {
289
310
  const current = await ownedWizard(userId, wizardId);
290
- throw new ServiceError("revision_conflict", "Der Wizard wurde inzwischen geändert.", {
311
+ throw new ServiceError("revision_conflict", bilingual("Der Wizard wurde inzwischen geändert.", "The wizard has been changed in the meantime."), {
291
312
  revision: current.revision,
292
313
  });
293
314
  }
@@ -308,7 +329,7 @@ export async function writeDraft(userId, wizardId, input, writer = { source: "st
308
329
  export async function editWizard(userId, wizardId, input, writer) {
309
330
  const w = await writableWizard(userId, wizardId);
310
331
  if (w.revision !== input.baseRevision) {
311
- throw new ServiceError("revision_conflict", "Der Wizard wurde inzwischen geändert.", {
332
+ throw new ServiceError("revision_conflict", bilingual("Der Wizard wurde inzwischen geändert.", "The wizard has been changed in the meantime."), {
312
333
  revision: w.revision,
313
334
  });
314
335
  }
@@ -318,7 +339,7 @@ export async function editWizard(userId, wizardId, input, writer) {
318
339
  }
319
340
  catch (err) {
320
341
  if (err instanceof OpError) {
321
- throw new ServiceError("invalid", err.message);
342
+ throw new ServiceError("invalid", saidOf(err));
322
343
  }
323
344
  throw err;
324
345
  }
@@ -380,7 +401,7 @@ export async function requireClean(w) {
380
401
  const files = await draftFiles(w.id);
381
402
  const issues = await checkDraft(w.projectId, w.draft, files.map((f) => f.path));
382
403
  if (issues.length) {
383
- throw new ServiceError("has_issues", "Der Wizard hat noch Fehler.", { issues });
404
+ throw new ServiceError("has_issues", bilingual("Der Wizard hat noch Fehler.", "The wizard still has errors."), { issues });
384
405
  }
385
406
  return { definition: w.draft, files };
386
407
  }
@@ -1,3 +1,4 @@
1
+ import { NotedError } from "../model-errors.js";
1
2
  /** A store refused: a list is full, a path is not one, a row is there already. */
2
- export class StoreError extends Error {
3
+ export class StoreError extends NotedError {
3
4
  }
@@ -1,4 +1,5 @@
1
- import { newCells, patchCells, rowKey, STORE_LIMITS, } from "@engenty-wizards/shared/store";
1
+ import { bilingual } from "@engenty-wizards/shared/run";
2
+ import { firstRowAt, newCells, patchCells, rowKey, STORE_LIMITS, } from "@engenty-wizards/shared/store";
2
3
  import { cleanPath, mimeForPath } from "@engenty-wizards/shared/workspace";
3
4
  import { and, asc, eq, inArray, like, lt, sql } from "drizzle-orm";
4
5
  import { nanoid } from "nanoid";
@@ -59,6 +60,7 @@ export async function saveRows(scope, def, input) {
59
60
  const existing = await db.query.storeRow.findMany({ where: inList(scope, def.id) });
60
61
  const byKey = new Map(existing.filter((r) => r.key).map((r) => [r.key, r]));
61
62
  let count = existing.length;
63
+ const at = firstRowAt(existing);
62
64
  for (const raw of input) {
63
65
  const key = rowKey(def, raw);
64
66
  const hit = key ? byKey.get(key) : undefined;
@@ -79,10 +81,17 @@ export async function saveRows(scope, def, input) {
79
81
  if (count >= STORE_LIMITS.rowsPerList) {
80
82
  throw new StoreError(`List "${def.id}" is full (${STORE_LIMITS.rowsPerList} rows).`);
81
83
  }
82
- const row = { id: nanoid(14), ...scope, list: def.id, key, cells };
84
+ const row = {
85
+ id: nanoid(14),
86
+ ...scope,
87
+ list: def.id,
88
+ key,
89
+ cells,
90
+ createdAt: new Date(at + added),
91
+ };
83
92
  await db.insert(schema.storeRow).values(row);
84
93
  if (key) {
85
- byKey.set(key, { ...row, createdAt: new Date(), updatedAt: new Date() });
94
+ byKey.set(key, { ...row, updatedAt: new Date() });
86
95
  }
87
96
  count++;
88
97
  added++;
@@ -109,7 +118,7 @@ export async function updateRow(scope, def, rowId, patch) {
109
118
  })
110
119
  : null;
111
120
  if (clash) {
112
- throw new StoreError("Diesen Eintrag gibt es schon.");
121
+ throw new StoreError(bilingual("Diesen Eintrag gibt es schon.", "This entry already exists."));
113
122
  }
114
123
  await db
115
124
  .update(schema.storeRow)
@@ -176,6 +185,14 @@ export async function storeFiles(scope, folder) {
176
185
  });
177
186
  return rows.map(toFile);
178
187
  }
188
+ /** Whether the wizard keeps any file for the holder: one row, not the whole list. */
189
+ export async function hasStoreFiles(scope) {
190
+ const row = await db.query.storeFile.findFirst({
191
+ where: ownFiles(scope),
192
+ columns: { path: true },
193
+ });
194
+ return row !== undefined;
195
+ }
179
196
  export async function readStoreFile(scope, rawPath) {
180
197
  const path = cleanPath(rawPath);
181
198
  const row = path
@@ -1,4 +1,4 @@
1
- import { newCells, patchCells, rowKey, STORE_LIMITS, } from "@engenty-wizards/shared/store";
1
+ import { firstRowAt, newCells, patchCells, rowKey, STORE_LIMITS, } from "@engenty-wizards/shared/store";
2
2
  import { and, asc, eq, inArray } from "drizzle-orm";
3
3
  import { nanoid } from "nanoid";
4
4
  import { db, schema } from "../db/client.js";
@@ -64,8 +64,7 @@ export async function saveSharedRows(wizardId, def, input) {
64
64
  });
65
65
  const byKey = new Map(existing.filter((r) => r.key).map((r) => [r.key, r]));
66
66
  let count = existing.length;
67
- // Rows stand in the order they came, also those saved in the same second.
68
- const at = Date.now();
67
+ const at = firstRowAt(existing);
69
68
  let added = 0;
70
69
  let updated = 0;
71
70
  for (const raw of input) {
@@ -10,6 +10,7 @@ import { gatewayTools, isHarnessVendor } from "../models.js";
10
10
  import { htmlToMarkdown } from "../render/convert.js";
11
11
  import { pythonToolDescription, sandboxCapabilities, shellToolDescription, } from "../sandbox/index.js";
12
12
  import { snapshotFile } from "../services/files.js";
13
+ import { hasStoreFiles } from "../store/index.js";
13
14
  import { browserTools } from "./browser.js";
14
15
  import { connectorTools } from "./connector.js";
15
16
  import { mailTools } from "./mail.js";
@@ -44,6 +45,13 @@ function isReadable(type, body) {
44
45
  }
45
46
  return odd <= sample.length * 0.01;
46
47
  }
48
+ /**
49
+ * Whether a step has no use for the wizard's store: it declares no tools and no connections,
50
+ * got no uploads, and the wizard keeps no lists. Its files may still be there (`buildStepTools`).
51
+ */
52
+ export function storeIdle(step, lists, uploads) {
53
+ return step.tools.length === 0 && !step.connections?.length && lists === 0 && uploads === 0;
54
+ }
47
55
  /** The tools an agent step may use: exactly what its definition allowlists. */
48
56
  export async function buildStepTools(step, ctx, resolved, uploads) {
49
57
  const tools = {};
@@ -139,8 +147,15 @@ export async function buildStepTools(step, ctx, resolved, uploads) {
139
147
  Object.assign(tools, await browserTools(ctx, assets, files));
140
148
  }
141
149
  // The wizard's lists and files, the documents the person gave and the project's documents are
142
- // always at hand.
143
- Object.assign(tools, storeTools(ctx, uploads, files));
150
+ // always at hand. An installed client gets tools over an MCP bridge its CLI starts for every
151
+ // call, seconds of its own: a step with no use for the store goes without its tools, and
152
+ // without others (Wissen, a workspace file) the client answers without the bridge.
153
+ const idle = isHarnessVendor(resolved.vendor) &&
154
+ storeIdle(step, ctx.def.lists?.length ?? 0, uploads.length) &&
155
+ !(await hasStoreFiles(ctx.store));
156
+ if (!idle) {
157
+ Object.assign(tools, storeTools(ctx, uploads, files));
158
+ }
144
159
  Object.assign(tools, await projectTools(ctx));
145
160
  Object.assign(tools, mailTools(step, ctx, files));
146
161
  Object.assign(tools, await connectorTools(step, ctx, files));
@@ -1,4 +1,5 @@
1
1
  import { pluginToolOf } from "@engenty-wizards/shared/definition";
2
+ import { bilingual } from "@engenty-wizards/shared/run";
2
3
  import { createTool } from "@mastra/core/tools";
3
4
  import { StepError } from "../engine/types.js";
4
5
  import { loadedPlugin, pluginIdsOf, pluginsOf } from "../plugins/registry.js";
@@ -38,7 +39,7 @@ async function toolOf(id, ctx) {
38
39
  const found = named && has.has(named.plugin) ? loadedPlugin(named.plugin)?.tools.get(named.tool) : undefined;
39
40
  if (!(named && found)) {
40
41
  const plugin = named?.plugin ?? id;
41
- throw new StepError(`Dieser Schritt braucht das Werkzeug „${id}“. Das Plugin „${plugin}“ ist hier nicht installiert.`);
42
+ throw new StepError(bilingual(`Dieser Schritt braucht das Werkzeug „${id}“. Das Plugin „${plugin}“ ist hier nicht installiert.`, `This step needs the tool “${id}”. The plugin “${plugin}” is not installed here.`));
42
43
  }
43
44
  return { plugin: named.plugin, tool: found };
44
45
  }
@@ -51,7 +52,7 @@ export async function callPluginTool(id, input, ctx) {
51
52
  const parsed = tool.inputSchema.safeParse(input);
52
53
  if (!parsed.success) {
53
54
  const issue = parsed.error.issues[0];
54
- throw new StepError(`„${id}“ bekam ungültige Angaben: ${issue?.path.join(".") || "input"} – ${issue?.message}`);
55
+ throw new StepError(bilingual(`„${id}“ bekam ungültige Angaben: ${issue?.path.join(".") || "input"} – ${issue?.message}`, `“${id}” got invalid input: ${issue?.path.join(".") || "input"} – ${issue?.message}`));
55
56
  }
56
57
  try {
57
58
  return await tool.execute(parsed.data, toolContext(ctx));
@@ -312,7 +312,7 @@ export async function renderFilm(html, size, media, onProgress) {
312
312
  out = mixed;
313
313
  }
314
314
  else {
315
- errors.push(`Der Ton konnte nicht gemischt werden: ${stderr.slice(-200)}`);
315
+ errors.push(`The sound could not be mixed: ${stderr.slice(-200)}`);
316
316
  }
317
317
  }
318
318
  return {
@@ -1,4 +1,5 @@
1
1
  import { allFields, dataRef, widgetSize, } from "@engenty-wizards/shared/definition";
2
+ import { bilingual } from "@engenty-wizards/shared/run";
2
3
  import { resolveRef } from "../engine/template.js";
3
4
  import { StepError } from "../engine/types.js";
4
5
  import { extFor, inlineAssetRefs, loadAsset } from "../files/storage.js";
@@ -106,7 +107,7 @@ async function runFilmStep(step, ctx, html, data, media, origin) {
106
107
  }
107
108
  });
108
109
  if (!film) {
109
- throw new StepError("Der Film konnte nicht gerendert werden: dazu braucht es ffmpeg und eine Zeitleiste im Widget.");
110
+ throw new StepError(bilingual("Der Film konnte nicht gerendert werden: dazu braucht es ffmpeg und eine Zeitleiste im Widget.", "The film could not be rendered: that needs ffmpeg and a timeline in the widget."));
110
111
  }
111
112
  if (film.errors.length) {
112
113
  await ctx.emit("info", {
@@ -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,An as i,Fn as a,Gt as o,Ht as s,Ut as c,Wt as l,Xt as u,an as d,rn as f,sn as p,tn as m}from"./ui-DTuixH4y.js";import{t as h}from"./preload-helper-CNEI7N0N.js";import{$ as g,H as _,V as v,gt as y}from"./index-B-D8UvL9.js";import{c as b,f as x}from"./settings-menu-BJm0CwOj.js";import{ReleaseNotes as S,loadReleases as C,releaseDate as w,releaseLabel as T}from"./ChangelogDialog-BcM1gXPM.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:a}){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)(i,{"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})]}),a?(0,k.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:a}):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[f]},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,i]=(0,E.useState)(``);(0,E.useEffect)(()=>{if(!e||t)return;let r=!1;return h(()=>import(`./oss-credits-BQQX0kvk.js`).then(e=>{r||n(e.default)}),[]),()=>{r=!0}},[e,t]),(0,E.useEffect)(()=>{e||i(``)},[e]);let a=r.trim().toLowerCase(),s=e=>a?e.filter(e=>A(a,e.name,e.license,e.description.de,e.description.en)):e,l=e=>a?e.filter(e=>A(a,e.name,e.license,e.version)):e,f=s(D),p=s(O),m=t?[{id:`shared`,label:d(`about.creditsShared`),packages:l(t.shared)},...t.groups.map(e=>({id:e.id,label:e.label,packages:l(e.packages)}))].filter(e=>e.packages.length>0):[],g=f.length===0&&p.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:d(`about.creditsHint`)}),(0,k.jsx)(o,{type:`search`,value:r,placeholder:d(`about.search`),onChange:e=>i(e.target.value)}),f.length>0?(0,k.jsx)(M,{title:d(`about.creditsProduct`),children:(0,k.jsx)(N,{credits:f})}):null,p.length>0?(0,k.jsx)(M,{title:d(`about.creditsBuiltWith`),children:(0,k.jsx)(N,{credits:p})}):null,t===null?(0,k.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,k.jsx)(u,{})}):m.length>0?(0,k.jsx)(M,{title:d(`about.creditsDeps`),hint:a?void 0:d(`about.creditsDepsHint`),children:m.map(e=>(0,k.jsx)(P,{label:e.label,packages:e.packages},e.id))}):null,t!==null&&g?(0,k.jsx)(c,{children:d(`about.noMatches`)}):null]})}var I=[`new`,`earlier`,`credits`],L=e=>d(e===`new`?`about.tab.new`:e===`earlier`?`about.tab.earlier`:`about.credits`),R=e=>e===1?d(`about.change`):d(`about.changes`,{n:e});function z({open:e,onClose:t,me:n}){let i=n?.mode===`local`,{data:o,latest:c}=_(i&&e),[f,h]=(0,E.useState)(null),[D,O]=(0,E.useState)(`new`),A=x(I.indexOf(D)),j=o?.newer&&c?c:g;(0,E.useEffect)(()=>{if(!e)return;let t=!1;return h(null),C(j===`0.4.3`?void 0:j).then(e=>{t||h(e)}),()=>{t=!0}},[e,j]);let M=f?.find(e=>e.version===`v${j}`)??f?.[0]??null,N=f?.filter(e=>e!==M)??[],P=i?o?.kind??null:`cloud`;return(0,k.jsxs)(s,{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)(l,{label:d(`common.close`),onClick:t,children:(0,k.jsx)(p,{className:`size-4`})})}),(0,k.jsxs)(`div`,{className:`flex flex-col items-center pt-4 text-center`,children:[(0,k.jsx)(y,{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:[d(`about.version`,{v:g}),P?` · ${d(`about.kind.${P}`)}`:``]})]}),i?(0,k.jsx)(`div`,{className:`mt-5`,children:(0,k.jsx)(v,{enabled:e})}):null,(0,k.jsx)(`div`,{className:`mt-6 flex justify-center`,children:(0,k.jsx)(r,{value:D,onChange:O,options:I.map(e=>({id:e,label:L(e)})),label:d(`about.title`)})}),(0,k.jsxs)(`div`,{className:m(`mt-5`,b(A)),children:[D===`new`?f===null?(0,k.jsx)(`div`,{className:`flex justify-center py-6 text-ink-3`,children:(0,k.jsx)(u,{})}):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:d(`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)(a,{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{In as r,Jt as i,Vn as a,Xt as o,Yt as s,cn as c,dn as l,in as u,on as d,pn as f,qt as p,tn as m}from"./ui-DrdqFaQt.js";import{t as h}from"./preload-helper-CNEI7N0N.js";import{H as g,U as _,W as v,_t as y}from"./index-BRDn-5v_.js";import{c as b,f as x}from"./settings-menu-CrVpArM_.js";import{ReleaseNotes as S,loadReleases as C,releaseDate as w,releaseLabel as T}from"./ChangelogDialog-DBjoIIHL.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:i,description:a}){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)(r,{"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:i})]}),a?(0,k.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:a}):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[c]},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 h(()=>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,u=e=>s?e.filter(e=>A(s,e.name,e.license,e.version)):e,d=c(D),f=c(O),p=t?[{id:`shared`,label:l(`about.creditsShared`),packages:u(t.shared)},...t.groups.map(e=>({id:e.id,label:e.label,packages:u(e.packages)}))].filter(e=>e.packages.length>0):[],g=d.length===0&&f.length===0&&p.length===0;return(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`p`,{className:`mb-4 text-[0.875rem] text-ink-3`,children:l(`about.creditsHint`)}),(0,k.jsx)(o,{type:`search`,value:r,placeholder:l(`about.search`),onChange:e=>a(e.target.value)}),d.length>0?(0,k.jsx)(M,{title:l(`about.creditsProduct`),children:(0,k.jsx)(N,{credits:d})}):null,f.length>0?(0,k.jsx)(M,{title:l(`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)(m,{})}):p.length>0?(0,k.jsx)(M,{title:l(`about.creditsDeps`),hint:s?void 0:l(`about.creditsDepsHint`),children:p.map(e=>(0,k.jsx)(P,{label:e.label,packages:e.packages},e.id))}):null,t!==null&&g?(0,k.jsx)(i,{children:l(`about.noMatches`)}):null]})}var I=[`new`,`earlier`,`credits`],L=e=>l(e===`new`?`about.tab.new`:e===`earlier`?`about.tab.earlier`:`about.credits`),R=e=>e===1?l(`about.change`):l(`about.changes`,{n:e});function z({open:e,onClose:t,me:n}){let r=n?.mode===`local`,{data:i,latest:o}=v(r&&e),[c,h]=(0,E.useState)(null),[D,O]=(0,E.useState)(`new`),A=x(I.indexOf(D)),j=i?.newer&&o?o:_;(0,E.useEffect)(()=>{if(!e)return;let t=!1;return h(null),C(j===`0.4.5`?void 0:j).then(e=>{t||h(e)}),()=>{t=!0}},[e,j]);let M=c?.find(e=>e.version===`v${j}`)??c?.[0]??null,N=c?.filter(e=>e!==M)??[],P=r?i?.kind??null:`cloud`;return(0,k.jsxs)(p,{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)(s,{label:l(`common.close`),onClick:t,children:(0,k.jsx)(f,{className:`size-4`})})}),(0,k.jsxs)(`div`,{className:`flex flex-col items-center pt-4 text-center`,children:[(0,k.jsx)(y,{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:[l(`about.version`,{v:_}),P?` · ${l(`about.kind.${P}`)}`:``]})]}),r?(0,k.jsx)(`div`,{className:`mt-5`,children:(0,k.jsx)(g,{enabled:e})}):null,(0,k.jsx)(`div`,{className:`mt-6 flex justify-center`,children:(0,k.jsx)(u,{value:D,onChange:O,options:I.map(e=>({id:e,label:L(e)})),label:l(`about.title`)})}),(0,k.jsxs)(`div`,{className:d(`mt-5`,b(A)),children:[D===`new`?c===null?(0,k.jsx)(`div`,{className:`flex justify-center py-6 text-ink-3`,children:(0,k.jsx)(m,{})}):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:l(`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)(a,{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{Gt as r,Ht as i,Ut as a,Xt as o,an as s,tn as c}from"./ui-DTuixH4y.js";import{t as l}from"./preload-helper-CNEI7N0N.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/,``):s(`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 l(async()=>{let{default:e}=await import(`./changelog-DfmWTlav.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:c(`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:s(`about.breaking`)}):null]})]},e.id)})})}function y({open:e,onClose:t,version:n}){let[c,l]=(0,u.useState)(null),[f,h]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||c)return;let t=!1;return _(n).then(e=>{t||l(e)}),()=>{t=!0}},[e,c,n]),(0,u.useEffect)(()=>{e||h(``)},[e]);let y=c?g(c,f):[];return(0,d.jsxs)(i,{open:e,onClose:t,title:s(`about.changelog`),wide:!0,height:`tall`,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:s(`about.changelogHint`)}),c===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(o,{})}):c.length===0?(0,d.jsx)(a,{children:s(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(r,{type:`search`,value:f,placeholder:s(`about.search`),onChange:e=>h(e.target.value)}),y.length===0?(0,d.jsx)(a,{children:s(`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{Jt as r,Xt as i,dn as a,on as o,qt as s,tn as c}from"./ui-DrdqFaQt.js";import{t as l}from"./preload-helper-CNEI7N0N.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/,``):a(`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 l(async()=>{let{default:e}=await import(`./changelog-D-12LwZB.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:o(`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:a(`about.breaking`)}):null]})]},e.id)})})}function y({open:e,onClose:t,version:n}){let[o,l]=(0,u.useState)(null),[f,h]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||o)return;let t=!1;return _(n).then(e=>{t||l(e)}),()=>{t=!0}},[e,o,n]),(0,u.useEffect)(()=>{e||h(``)},[e]);let y=o?g(o,f):[];return(0,d.jsxs)(s,{open:e,onClose:t,title:a(`about.changelog`),wide:!0,height:`tall`,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:a(`about.changelogHint`)}),o===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(c,{})}):o.length===0?(0,d.jsx)(r,{children:a(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(i,{type:`search`,value:f,placeholder:a(`about.search`),onChange:e=>h(e.target.value)}),y.length===0?(0,d.jsx)(r,{children:a(`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};