wizards 0.2.32 → 0.2.34

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 (31) hide show
  1. package/apps/runtime/dist/cli/main.js +26 -5
  2. package/apps/runtime/dist/cli/mcp.js +6 -33
  3. package/apps/runtime/dist/cli/menu.js +144 -0
  4. package/apps/runtime/dist/cli/start.js +56 -12
  5. package/apps/runtime/dist/cli/status.js +56 -10
  6. package/apps/runtime/dist/cli/update.js +1 -1
  7. package/apps/runtime/dist/index.js +6 -1
  8. package/apps/web/dist/assets/{Account-5PZncmqk.js → Account-Bx3tKERT.js} +1 -1
  9. package/apps/web/dist/assets/{ChangelogDialog-QMuDmALk.js → ChangelogDialog-WyVaImjd.js} +1 -1
  10. package/apps/web/dist/assets/{EditorPage-BeM0smMQ.js → EditorPage--6_nN50C.js} +1 -1
  11. package/apps/web/dist/assets/{FlowPreview-CUebTdyh.js → FlowPreview-DC0Yl6bP.js} +1 -1
  12. package/apps/web/dist/assets/{Harness-Be76qecO.js → Harness-DbaZ3G6S.js} +1 -1
  13. package/apps/web/dist/assets/{HomePage-DH3Dzo9x.js → HomePage-D_JydnMC.js} +1 -1
  14. package/apps/web/dist/assets/{ImportWizard-oEjwT_0J.js → ImportWizard-LV9uE8aL.js} +1 -1
  15. package/apps/web/dist/assets/{LocalRuntime-CH8_zIK4.js → LocalRuntime-FTYk-ibA.js} +1 -1
  16. package/apps/web/dist/assets/{NewWizardPage-CDEwNfx-.js → NewWizardPage-CHHztn0G.js} +2 -2
  17. package/apps/web/dist/assets/{ProjectPage-DR_yX4Y8.js → ProjectPage-BVFCdmwA.js} +1 -1
  18. package/apps/web/dist/assets/{PublicRunner-Dmw-7x9t.js → PublicRunner-BrePj0DG.js} +1 -1
  19. package/apps/web/dist/assets/{RunDrawer-Bq23pmJa.js → RunDrawer-PH_MjEMM.js} +1 -1
  20. package/apps/web/dist/assets/{RunnerView-0mWfQEsS.js → RunnerView-B9RUgpx4.js} +1 -1
  21. package/apps/web/dist/assets/{SettingsPage-CyEalhx-.js → SettingsPage-BOYNQme7.js} +1 -1
  22. package/apps/web/dist/assets/{SetupPage-DHuFp0PF.js → SetupPage-e7r976rH.js} +1 -1
  23. package/apps/web/dist/assets/{SharePage-vr48Pkdg.js → SharePage-9jgm-MUN.js} +1 -1
  24. package/apps/web/dist/assets/changelog-B6AlU2mc.js +1 -0
  25. package/apps/web/dist/assets/{esm-Ckl7le0A.js → esm-fVkImIQu.js} +1 -1
  26. package/apps/web/dist/assets/{index-DyiZlzJ2.js → index-Dzs5btCG.js} +3 -3
  27. package/apps/web/dist/assets/{meta-D5QeOYH-.js → meta-DqAfGI9S.js} +1 -1
  28. package/apps/web/dist/assets/{settings-menu-cjRkf6JU.js → settings-menu-Cb7ifxy-.js} +1 -1
  29. package/apps/web/dist/index.html +1 -1
  30. package/package.json +1 -1
  31. package/apps/web/dist/assets/changelog-tH5O-JCg.js +0 -1
@@ -2,18 +2,21 @@ import { apps, connectCommand } from "./connect.js";
2
2
  import { layout, packageVersion, readInstallNote } from "./home.js";
3
3
  import { CLIENTS, nodeIsCurrent } from "./machine.js";
4
4
  import { mcp } from "./mcp.js";
5
+ import { menu } from "./menu.js";
5
6
  import { command, setup } from "./setup.js";
6
7
  import { open, start } from "./start.js";
7
- import { autostart, status, stop } from "./status.js";
8
+ import { autostart, restart, status, stop } from "./status.js";
8
9
  import { update } from "./update.js";
9
10
  const HELP = `engenty wizards ${packageVersion()}
10
11
 
11
- ${command()} [start] start it and open the studio; the first time, the setup runs first
12
+ ${command()} what runs, and a menu: start, stop, update …; the first time, the setup runs first
13
+ ${command()} start start it and open the studio
12
14
  ${command()} setup guided setup: an AI client to think with, ffmpeg, start at login
13
15
  ${command()} open let this browser into the running studio (--print: only show the link)
14
16
  ${command()} status what is installed and what runs
15
17
  ${command()} doctor status, and what is wrong
16
18
  ${command()} stop stop it; the data is kept
19
+ ${command()} restart stop it and start it again (after an update: the new version)
17
20
  ${command()} update the newest version
18
21
  ${command()} autostart start it at login: on, off (macOS: a LaunchAgent; Linux: a systemd service)
19
22
  ${command()} connect your wizards in your AI apps: every app found, or name them —
@@ -26,6 +29,7 @@ const HELP = `engenty wizards ${packageVersion()}
26
29
  --yes, -y ask nothing and install nothing optional
27
30
  --client <name> install this AI client without asking: ${CLIENTS.map((c) => c.id).join(", ")}
28
31
  --no-open start without opening the browser
32
+ --service, -s start as a service, detached from this terminal; \`wizards stop\` stops it
29
33
  --version, --help
30
34
 
31
35
  Everything lives in ~/.engenty/wizards (ENGENTY_HOME moves it); settings go into its .env.
@@ -37,6 +41,7 @@ function parse(argv) {
37
41
  apps: [],
38
42
  yes: false,
39
43
  open: true,
44
+ service: false,
40
45
  print: false,
41
46
  clients: [],
42
47
  };
@@ -48,6 +53,9 @@ function parse(argv) {
48
53
  else if (arg === "--no-open") {
49
54
  args.open = false;
50
55
  }
56
+ else if (arg === "--service" || arg === "-s") {
57
+ args.service = true;
58
+ }
51
59
  else if (arg === "--print") {
52
60
  args.print = true;
53
61
  }
@@ -80,7 +88,6 @@ function parse(argv) {
80
88
  args.command = arg;
81
89
  }
82
90
  }
83
- args.command ||= "start";
84
91
  return args;
85
92
  }
86
93
  async function main(argv) {
@@ -91,6 +98,14 @@ async function main(argv) {
91
98
  }
92
99
  const paths = layout();
93
100
  const setupOptions = { yes: args.yes, clients: args.clients };
101
+ if (!args.command) {
102
+ // On a terminal, without options: the menu. Anywhere else it starts, as it always did.
103
+ const plain = argv.length === 0 && process.stdin.isTTY && process.stdout.isTTY;
104
+ if (plain) {
105
+ return menu(paths, setupOptions, HELP);
106
+ }
107
+ args.command = "start";
108
+ }
94
109
  switch (args.command) {
95
110
  case "help":
96
111
  console.log(HELP);
@@ -107,11 +122,15 @@ async function main(argv) {
107
122
  return next === null ? 130 : 0;
108
123
  }
109
124
  }
110
- return start(paths, { open: args.open });
125
+ return start(paths, { open: args.open, background: args.service });
111
126
  }
112
127
  case "setup": {
113
128
  const next = await setup(paths, setupOptions);
114
- return next === "start" ? start(paths, { open: args.open }) : next === null ? 130 : 0;
129
+ return next === "start"
130
+ ? start(paths, { open: args.open, background: args.service })
131
+ : next === null
132
+ ? 130
133
+ : 0;
115
134
  }
116
135
  case "open":
117
136
  return open(paths, args.print);
@@ -121,6 +140,8 @@ async function main(argv) {
121
140
  return status(paths, true);
122
141
  case "stop":
123
142
  return stop(paths);
143
+ case "restart":
144
+ return restart(paths);
124
145
  case "update":
125
146
  return update(paths);
126
147
  case "autostart":
@@ -1,19 +1,8 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdirSync, openSync, readFileSync } from "node:fs";
1
+ import { readFileSync } from "node:fs";
3
2
  import { join } from "node:path";
4
3
  import { createInterface } from "node:readline";
5
4
  import { LOCAL_CLIENT_HEADER, LOCAL_MCP_HEADER, mintLocalTicket } from "../auth/local-ticket.js";
6
- import { runningRuntime, settings } from "./start.js";
7
- /**
8
- * `wizards mcp`: this install's MCP server over stdio, for AI clients that start their
9
- * servers as a command — Claude Desktop, Cursor, Codex and the ChatGPT app, VS Code, Windsurf,
10
- * Gemini CLI, Goose, OpenClaw, LM Studio. Each message goes on to the running runtime's
11
- * `/api/mcp`, signed with the data folder's secret, so no client's config holds a key and a new
12
- * port after a restart changes nothing. When nothing runs, the runtime is started.
13
- *
14
- * stdout carries only MCP messages; everything else goes to stderr.
15
- */
16
- const START_TIMEOUT_MS = 60_000;
5
+ import { runningRuntime, settings, startInBackground } from "./start.js";
17
6
  /** The JSON-RPC messages of a response: a JSON body (one or a batch) or a server-sent stream. */
18
7
  export function messagesOf(contentType, body) {
19
8
  if (!body.trim()) {
@@ -48,17 +37,6 @@ function readSecret(paths, dataDir) {
48
37
  return null;
49
38
  }
50
39
  }
51
- /** Starts the runtime in the background, the way `wizards start --no-open` would. */
52
- function startInBackground(paths) {
53
- mkdirSync(paths.logs, { recursive: true });
54
- const log = openSync(join(paths.logs, "runtime.log"), "a");
55
- const child = spawn(process.execPath, [process.argv[1], "start", "--no-open"], {
56
- detached: true,
57
- stdio: ["ignore", log, log],
58
- env: process.env,
59
- });
60
- child.unref();
61
- }
62
40
  export async function mcp(paths) {
63
41
  const { dataDir } = settings(paths);
64
42
  let running = null;
@@ -71,16 +49,11 @@ export async function mcp(paths) {
71
49
  return found;
72
50
  }
73
51
  process.stderr.write("engenty wizards is not running; starting it …\n");
74
- startInBackground(paths);
75
- const began = Date.now();
76
- while (Date.now() - began < START_TIMEOUT_MS) {
77
- await new Promise((wait) => setTimeout(wait, 300));
78
- const started = await runningRuntime(dataDir);
79
- if (started) {
80
- return started;
81
- }
52
+ const started = await startInBackground(paths);
53
+ if (started) {
54
+ return started;
82
55
  }
83
- throw new Error(`engenty wizards did not start within a minute; see ${join(paths.logs, "runtime.log")}.`);
56
+ throw new Error(`engenty wizards did not start; see ${join(paths.logs, "runtime.log")}.`);
84
57
  })();
85
58
  running.catch(() => {
86
59
  running = null;
@@ -0,0 +1,144 @@
1
+ import * as p from "@clack/prompts";
2
+ import { updateStatus } from "../update.js";
3
+ import { autostartState, setAutostart } from "./autostart.js";
4
+ import { connectCommand } from "./connect.js";
5
+ import { packageVersion, readInstallNote } from "./home.js";
6
+ import { command, setup } from "./setup.js";
7
+ import { open, runningRuntime, settings, start } from "./start.js";
8
+ import { restart, status, stop } from "./status.js";
9
+ import { badge, cyan, dim, no, ok } from "./ui.js";
10
+ import { update } from "./update.js";
11
+ async function look(paths) {
12
+ const { dataDir } = settings(paths);
13
+ const [running, atLogin, release] = await Promise.all([
14
+ runningRuntime(dataDir),
15
+ autostartState(paths),
16
+ updateStatus().catch(() => null),
17
+ ]);
18
+ return { running, atLogin, release };
19
+ }
20
+ function report({ running, atLogin, release }) {
21
+ const lines = [
22
+ running
23
+ ? `${ok} running ${cyan(running.url)} ${dim(`pid ${running.pid}, since ${new Date(running.startedAt).toLocaleString()}`)}`
24
+ : `${no} not running`,
25
+ ];
26
+ if (!("unavailable" in atLogin)) {
27
+ lines.push(atLogin.on ? `${ok} starts at login` : `${no} does not start at login`);
28
+ }
29
+ if (release?.newer) {
30
+ lines.push(`${cyan("↑")} ${release.latest} is out ${dim(`(you have ${release.current})`)}`);
31
+ }
32
+ return lines.join("\n");
33
+ }
34
+ function choices({ running, atLogin, release }) {
35
+ const options = running
36
+ ? [
37
+ { value: "open", label: "Open the studio", hint: "in your browser" },
38
+ { value: "restart", label: "Restart" },
39
+ { value: "stop", label: "Stop", hint: "the data is kept" },
40
+ ]
41
+ : [
42
+ { value: "start", label: "Start", hint: "in the background, opens the studio" },
43
+ { value: "foreground", label: "Start here", hint: "in this terminal; Ctrl-C stops it" },
44
+ ];
45
+ options.push({
46
+ value: "update",
47
+ label: "Update",
48
+ hint: release?.newer
49
+ ? `${release.latest} is out`
50
+ : release?.latest
51
+ ? "you have the newest"
52
+ : undefined,
53
+ });
54
+ if (!("unavailable" in atLogin)) {
55
+ options.push({
56
+ value: "autostart",
57
+ label: atLogin.on ? "Don't start at login" : "Start at login",
58
+ });
59
+ }
60
+ options.push({ value: "connect", label: "Connect AI apps", hint: "your wizards in Claude, Cursor, Codex …" }, { value: "status", label: "Status", hint: "what is installed, and what is wrong" }, { value: "setup", label: "Setup", hint: "AI client, ffmpeg, start at login" }, { value: "help", label: "Help", hint: "every command" }, { value: "quit", label: "Quit", hint: running ? "it keeps running" : undefined });
61
+ return options;
62
+ }
63
+ /**
64
+ * `wizards` on a terminal: what runs, and a menu of what the commands do. The first time, the
65
+ * setup runs first. Returns the exit code; "Start here" ends it with the runtime in the
66
+ * foreground.
67
+ */
68
+ export async function menu(paths, setupOptions, help) {
69
+ if (!readInstallNote(paths).setupAt) {
70
+ const next = await setup(paths, setupOptions);
71
+ if (next === null) {
72
+ return 130;
73
+ }
74
+ if (next === "start") {
75
+ await start(paths, { open: true, background: true });
76
+ }
77
+ }
78
+ p.intro(`${badge("engenty wizards")} ${dim(packageVersion())}`);
79
+ for (;;) {
80
+ const spinner = p.spinner();
81
+ spinner.start("Looking at what runs");
82
+ const state = await look(paths);
83
+ spinner.stop(report(state));
84
+ const action = await p.select({ message: "What now?", options: choices(state) });
85
+ if (p.isCancel(action) || action === "quit") {
86
+ p.outro(dim(`${command()} opens this again; ${command()} help lists every command.`));
87
+ return 0;
88
+ }
89
+ switch (action) {
90
+ case "start":
91
+ await start(paths, { open: true, background: true });
92
+ break;
93
+ case "foreground":
94
+ p.outro("Starting engenty wizards here");
95
+ return start(paths, { open: true });
96
+ case "open":
97
+ await open(paths, false);
98
+ break;
99
+ case "restart":
100
+ await restart(paths);
101
+ break;
102
+ case "stop":
103
+ await stop(paths);
104
+ break;
105
+ case "update": {
106
+ if ((await update(paths)) !== 0) {
107
+ break;
108
+ }
109
+ // This menu is still the old version: what runs restarts into the new one, then it ends.
110
+ if (state.running) {
111
+ await restart(paths);
112
+ }
113
+ p.outro(`Updated. ${cyan(command())} opens the new version.`);
114
+ return 0;
115
+ }
116
+ case "autostart":
117
+ if (!("unavailable" in state.atLogin)) {
118
+ try {
119
+ await setAutostart(paths, !state.atLogin.on);
120
+ }
121
+ catch (error) {
122
+ p.log.warn(`Starting at login could not be switched: ${error.message}`);
123
+ }
124
+ }
125
+ break;
126
+ case "connect":
127
+ await connectCommand(paths, [], false);
128
+ break;
129
+ case "status":
130
+ await status(paths, true);
131
+ break;
132
+ case "setup": {
133
+ const next = await setup(paths, setupOptions);
134
+ if (next === "start" && !state.running) {
135
+ await start(paths, { open: true, background: true });
136
+ }
137
+ break;
138
+ }
139
+ case "help":
140
+ console.log(help);
141
+ break;
142
+ }
143
+ }
144
+ }
@@ -1,6 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomBytes } from "node:crypto";
3
- import { existsSync, mkdirSync, readFileSync } from "node:fs";
3
+ import { existsSync, mkdirSync, openSync, readFileSync } from "node:fs";
4
4
  import { createServer } from "node:net";
5
5
  import { join, resolve } from "node:path";
6
6
  import { styleText } from "node:util";
@@ -96,9 +96,48 @@ function show(url, entry, open) {
96
96
  console.log(styleText("dim", " The link lets one browser in and works once."));
97
97
  }
98
98
  }
99
+ /** The command of this install, as it is on disk now: `wizards <args>`. */
100
+ function spawnCommand(paths, args, options) {
101
+ const wrapper = join(paths.bin, "wizards");
102
+ return existsSync(wrapper)
103
+ ? spawn(wrapper, args, options)
104
+ : spawn(process.execPath, [join(packageRoot, "bin/wizards.mjs"), ...args], options);
105
+ }
106
+ /**
107
+ * `wizards start --no-open` detached from this terminal, its output in logs/runtime.log; the
108
+ * runtime once it answers, or null when it ended or did not answer within a minute.
109
+ */
110
+ export async function startInBackground(paths) {
111
+ const { dataDir } = settings(paths);
112
+ mkdirSync(paths.logs, { recursive: true });
113
+ const log = openSync(join(paths.logs, "runtime.log"), "a");
114
+ const child = spawnCommand(paths, ["start", "--no-open"], {
115
+ cwd: paths.home,
116
+ detached: true,
117
+ stdio: ["ignore", log, log],
118
+ });
119
+ let exited = false;
120
+ child.on("error", () => {
121
+ exited = true;
122
+ });
123
+ child.on("exit", () => {
124
+ exited = true;
125
+ });
126
+ child.unref();
127
+ const began = Date.now();
128
+ while (!exited && Date.now() - began < START_TIMEOUT_MS) {
129
+ await new Promise((wait) => setTimeout(wait, 300));
130
+ const started = await runningRuntime(dataDir);
131
+ if (started) {
132
+ return started;
133
+ }
134
+ }
135
+ return null;
136
+ }
99
137
  /**
100
- * Starts the runtime of this install in the foreground and opens the studio. If one already
101
- * runs on the same data folder (another terminal, the desktop app), that one is opened instead.
138
+ * Starts the runtime of this install and opens the studio: in the foreground, or with
139
+ * `background` detached from this terminal. If one already runs on the same data folder
140
+ * (another terminal, the desktop app), that one is opened instead.
102
141
  */
103
142
  export async function start(paths, options) {
104
143
  const { fileEnv, dataDir, port: wanted, appUrl } = settings(paths);
@@ -110,6 +149,16 @@ export async function start(paths, options) {
110
149
  console.log(styleText("dim", " It was already running; stop it with `wizards stop`."));
111
150
  return 0;
112
151
  }
152
+ if (options.background) {
153
+ const started = await startInBackground(paths);
154
+ if (!started) {
155
+ console.error(`engenty wizards did not start; see ${join(paths.logs, "runtime.log")}.`);
156
+ return 1;
157
+ }
158
+ show(started.url, entryUrl(started, dataDir), options.open);
159
+ console.log(styleText("dim", ` It runs in the background; stop it with \`wizards stop\`. Its log: ${join(paths.logs, "runtime.log")}`));
160
+ return 0;
161
+ }
113
162
  const port = wanted ?? (await freePort());
114
163
  if (!wanted && port !== DEFAULT_PORT) {
115
164
  console.log(styleText("dim", ` Port ${DEFAULT_PORT} is taken, using ${port}.`));
@@ -160,15 +209,10 @@ export async function start(paths, options) {
160
209
  if (code !== RESTART_EXIT) {
161
210
  return code;
162
211
  }
163
- // Updated: the command as it is on disk now starts the new version, in this terminal or
164
- // under the login item, which keeps waiting on this process.
165
- console.log(styleText("dim", " Updated; starting the new version."));
166
- const wrapper = join(paths.bin, "wizards");
167
- current = existsSync(wrapper)
168
- ? spawn(wrapper, ["start", "--no-open"], { stdio: "inherit" })
169
- : spawn(process.execPath, [join(packageRoot, "bin/wizards.mjs"), "start", "--no-open"], {
170
- stdio: "inherit",
171
- });
212
+ // Updated or `wizards restart`: the command as it is on disk now starts it again, in this
213
+ // terminal or under the login item, which keeps waiting on this process.
214
+ console.log(styleText("dim", " Starting it again."));
215
+ current = spawnCommand(paths, ["start", "--no-open"], { stdio: "inherit" });
172
216
  return new Promise((done) => {
173
217
  current.on("error", () => done(1));
174
218
  current.on("exit", (exit) => done(exit ?? 0));
@@ -3,7 +3,7 @@ import { join } from "node:path";
3
3
  import { autostartState, setAutostart } from "./autostart.js";
4
4
  import { installedByScript, isCheckout, packageRoot, packageVersion } from "./home.js";
5
5
  import { detectClients, findChrome, findFfmpeg, nodeIsCurrent } from "./machine.js";
6
- import { runningRuntime, settings } from "./start.js";
6
+ import { entryUrl, runningRuntime, settings, startInBackground } from "./start.js";
7
7
  import { bad, badge, cyan, dim, no, ok, tilde } from "./ui.js";
8
8
  /**
9
9
  * What is installed and what runs. With `checks` (`doctor`) it also says what is wrong and
@@ -68,6 +68,19 @@ export async function status(paths, checks) {
68
68
  console.log("");
69
69
  return problems.length ? 1 : 0;
70
70
  }
71
+ /** Waits for a process to end; false when it still runs after `ms`. */
72
+ async function ended(pid, ms) {
73
+ for (let waited = 0; waited < ms; waited += 100) {
74
+ try {
75
+ process.kill(pid, 0);
76
+ }
77
+ catch {
78
+ return true;
79
+ }
80
+ await new Promise((wait) => setTimeout(wait, 100));
81
+ }
82
+ return false;
83
+ }
71
84
  /** Stops the runtime that runs on this install's data folder. */
72
85
  export async function stop(paths) {
73
86
  const { dataDir } = settings(paths);
@@ -77,19 +90,52 @@ export async function stop(paths) {
77
90
  return 0;
78
91
  }
79
92
  process.kill(running.pid, "SIGTERM");
80
- for (let waited = 0; waited < 8000; waited += 100) {
81
- try {
82
- process.kill(running.pid, 0);
83
- }
84
- catch {
85
- console.log(`Stopped (pid ${running.pid}). Your data is kept.`);
86
- return 0;
87
- }
88
- await new Promise((wait) => setTimeout(wait, 100));
93
+ if (await ended(running.pid, 8000)) {
94
+ console.log(`Stopped (pid ${running.pid}). Your data is kept.`);
95
+ return 0;
89
96
  }
90
97
  console.error(`The runtime (pid ${running.pid}) did not stop within 8 seconds.`);
91
98
  return 1;
92
99
  }
100
+ /**
101
+ * Stops the runtime and starts it again, the version on disk now. One the command started (a
102
+ * terminal, the login item) is started again by that command, where it ran; any other is
103
+ * stopped and started in the background. When nothing runs, it is started in the background.
104
+ */
105
+ export async function restart(paths) {
106
+ const { dataDir } = settings(paths);
107
+ const running = await runningRuntime(dataDir);
108
+ if (running?.restarts && process.platform !== "win32") {
109
+ process.kill(running.pid, "SIGUSR2");
110
+ for (let waited = 0; waited < 60_000; waited += 300) {
111
+ await new Promise((wait) => setTimeout(wait, 300));
112
+ const again = await runningRuntime(dataDir);
113
+ if (again && again.pid !== running.pid) {
114
+ console.log(`${ok} Restarted: ${cyan(again.url)} ${dim(`pid ${again.pid}`)}`);
115
+ return 0;
116
+ }
117
+ }
118
+ console.error("engenty wizards did not start again within a minute.");
119
+ return 1;
120
+ }
121
+ if (running) {
122
+ process.kill(running.pid, "SIGTERM");
123
+ if (!(await ended(running.pid, 8000))) {
124
+ console.error(`The runtime (pid ${running.pid}) did not stop within 8 seconds.`);
125
+ return 1;
126
+ }
127
+ }
128
+ const started = await startInBackground(paths);
129
+ if (!started) {
130
+ console.error(`engenty wizards did not start; see ${join(paths.logs, "runtime.log")}.`);
131
+ return 1;
132
+ }
133
+ console.log(`${ok} ${running ? "Restarted" : "Started"}: ${cyan(started.url)} ${dim(`pid ${started.pid}, in the background`)}`);
134
+ if (!running) {
135
+ console.log(` Open the studio: ${entryUrl(started, dataDir)}`);
136
+ }
137
+ return 0;
138
+ }
93
139
  /** `autostart [on|off]`: whether it starts at login, and the switch. */
94
140
  export async function autostart(paths, value) {
95
141
  if (value && value !== "on" && value !== "off") {
@@ -52,7 +52,7 @@ export async function update(paths) {
52
52
  rmSync(tmp, { recursive: true, force: true });
53
53
  }
54
54
  if (await runningRuntime(settings(paths).dataDir)) {
55
- console.log(` The runtime that is running is still the old one. Restart it: ${cyan("wizards stop")}, then ${cyan("wizards")}.`);
55
+ console.log(` The runtime that is running is still the old one. Restart it: ${cyan("wizards restart")}`);
56
56
  }
57
57
  return 0;
58
58
  }
@@ -15,7 +15,7 @@ import { syncMarketplace } from "./services/marketplace.js";
15
15
  import { purgeExpiredRuns } from "./services/shares.js";
16
16
  import { purgeUnusedStores } from "./store/index.js";
17
17
  import { LOCAL_TENANT } from "./tenants/tenant.js";
18
- import { onRestart } from "./update.js";
18
+ import { onRestart, RESTART_EXIT } from "./update.js";
19
19
  await migrateControlDb();
20
20
  // What the linked account's plan confirmed last: the Pro modules it includes load with the rest.
21
21
  await loadEntitlement();
@@ -61,6 +61,7 @@ const server = serve({ fetch: withoutBasePath, port: env.port, hostname: env.hos
61
61
  port: info.port,
62
62
  url: env.appUrl,
63
63
  startedAt: new Date().toISOString(),
64
+ restarts: process.env.ENGENTY_WIZARDS_RESTARTS === "1",
64
65
  });
65
66
  }
66
67
  });
@@ -90,3 +91,7 @@ async function shutdown(code = 0) {
90
91
  process.on("SIGINT", () => shutdown());
91
92
  process.on("SIGTERM", () => shutdown());
92
93
  onRestart((code) => void shutdown(code));
94
+ // `wizards restart`: the command that started it starts it again, where it ran.
95
+ if (process.env.ENGENTY_WIZARDS_RESTARTS === "1" && process.platform !== "win32") {
96
+ process.on("SIGUSR2", () => shutdown(RESTART_EXIT));
97
+ }
@@ -1 +1 @@
1
- import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{D as r,Q as i}from"./surface-CywgBXMy.js";import{D as a,G as o,H as s,c,f as l,g as u,h as d,j as f,k as p,n as ee,o as m,r as h,s as g,t as _,x as v}from"./ui-DyazyiaK.js";import{n as y,r as b}from"./upload-Dl_w8YOa.js";import{t as x}from"./external-link-CbxUCKS8.js";import{B as te,H as S,I as C,U as w,W as T,_t as E,at as D,ft as O}from"./index-DyiZlzJ2.js";import{n as k}from"./LocalRuntime-CH8_zIK4.js";var A={name:`hard-drive`,size:24,node:[[`path`,{d:`M10 16h.01`,key:`1bzywj`}],[`path`,{d:`M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`18tbho`}],[`path`,{d:`M21.946 12.013H2.054`,key:`zqlbp7`}],[`path`,{d:`M6 16h.01`,key:`1pmjb7`}]]};A.node;var j=o(A),M={name:`layout-grid`,size:24,node:[[`rect`,{width:`7`,height:`7`,x:`3`,y:`3`,rx:`1`,key:`1g98yp`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`3`,rx:`1`,key:`6d4xhi`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`14`,rx:`1`,key:`nxv5o0`}],[`rect`,{width:`7`,height:`7`,x:`3`,y:`14`,rx:`1`,key:`1bb6yr`}]]};M.node;var N=o(M),P={name:`list`,size:24,node:[[`path`,{d:`M3 5h.01`,key:`18ugdj`}],[`path`,{d:`M3 12h.01`,key:`nlz23k`}],[`path`,{d:`M3 19h.01`,key:`noohij`}],[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M8 12h13`,key:`1za7za`}],[`path`,{d:`M8 19h13`,key:`m83p4d`}]]};P.node;var F=o(P),I=e(t(),1),L=e=>[`project-files`,e];function R(e){return r({queryKey:L(e),queryFn:()=>v.get(`/api/studio/projects/${e}/files`),refetchInterval:e=>e.state.data?.files.some(e=>e.status===`pending`)?2e3:!1})}function z(e,t){return a(`/api/studio/projects/${e}/files/${t}/content`)}function B(e,t=!1){let n=i(),[r,a]=(0,I.useState)(!1),[o,s]=(0,I.useState)(null),c=()=>n.invalidateQueries({queryKey:L(e)}),l=async e=>{s(null);try{await e()}catch(e){s(e.message)}finally{await c()}};return{busy:r,error:o,readOnly:t,upload:async(t,n)=>{a(!0),await l(async()=>{for(let r of n)await v.upload(`/api/studio/projects/${e}/files?kind=${t}`,r),await c()}),a(!1)},describe:(t,n)=>l(()=>v.patch(`/api/studio/projects/${e}/files/${t}`,{description:n})),remove:t=>l(()=>v.del(`/api/studio/projects/${e}/files/${t}`)),reindex:t=>l(()=>v.post(`/api/studio/projects/${e}/files/${t}/reindex`)),order:(t,n)=>l(()=>v.put(`/api/studio/projects/${e}/files/order`,{kind:t,ids:n}))}}function V(e,t){let n=`wz.layout.${e}`,[r,i]=(0,I.useState)(()=>{try{let e=localStorage.getItem(n);return e===`list`||e===`cards`?e:t}catch{return t}});return[r,()=>i(e=>{let t=e===`list`?`cards`:`list`;try{localStorage.setItem(n,t)}catch{}return t})]}function H(e,t,n=700){let[r,i]=(0,I.useState)(`idle`),[a,o]=(0,I.useState)(null),s=JSON.stringify(e),c=(0,I.useRef)(s),l=(0,I.useRef)({value:e,json:s,save:t});l.current={value:e,json:s,save:t};let u=(0,I.useRef)(Promise.resolve()),d=(0,I.useCallback)(()=>{let e=l.current;e.json!==c.current&&(c.current=e.json,i(`saving`),u.current=u.current.then(async()=>{try{await e.save(e.value),o(null),i(`saved`)}catch(e){c.current=``,o(e.message),i(`error`)}}))},[]);return(0,I.useEffect)(()=>{if(s===c.current)return;let e=setTimeout(d,n);return()=>clearTimeout(e)},[s,n,d]),(0,I.useEffect)(()=>d,[d]),{state:r,error:a}}function U(e){return e<1e6?`${Math.max(1,Math.round(e/1e3))} KB`:`${(e/1e6).toFixed(1)} MB`}var W=e(n(),1);function G({id:e,children:t}){return(0,W.jsx)(`div`,{id:e,className:`scroll-mt-24 max-md:scroll-mt-36`,children:t})}function K({title:e,hint:t,save:n,action:r,locked:i,plain:a,children:o}){return(0,W.jsxs)(`section`,{className:`flex flex-col gap-2.5`,children:[(0,W.jsxs)(`div`,{className:`flex items-start justify-between gap-4 px-1`,children:[(0,W.jsxs)(`div`,{className:`min-w-0`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,W.jsx)(`h2`,{className:`font-display font-semibold text-lg leading-tight`,children:e}),n?.state===`saving`?(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-[0.75rem] text-ink-3`,children:[(0,W.jsx)(l,{className:`size-3`}),` `,f(`project.saving`)]}):n?.state===`saved`?(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-[0.75rem] text-moss`,children:[(0,W.jsx)(s,{className:`size-3.5`}),` `,f(`settings.saved`)]}):null]}),t?(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-snug`,children:t}):null]}),r?(0,W.jsx)(`div`,{className:`shrink-0`,children:r}):null]}),a?o:(0,W.jsxs)(ee,{className:`p-3.5 sm:p-5`,children:[i?(0,W.jsx)(`fieldset`,{disabled:!0,className:`min-w-0`,children:o}):o,n?.state===`error`&&n.error?(0,W.jsx)(`p`,{className:`mt-4 text-[0.875rem] text-rose`,children:n.error}):null]})]})}function q({children:e,layout:t,onToggle:n}){return(0,W.jsxs)(`div`,{className:`mb-3 flex items-start gap-2`,children:[(0,W.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,W.jsx)(`div`,{className:`w-56 max-w-full transition-[width] duration-200 focus-within:w-full has-[input:not(:placeholder-shown)]:w-full`,children:e})}),(0,W.jsx)(m,{label:f(t===`list`?`project.viewCards`:`project.viewList`),onClick:n,children:t===`list`?(0,W.jsx)(N,{className:`size-4`}):(0,W.jsx)(F,{className:`size-4`})})]})}function J({value:e,onChange:t,onEnter:n,placeholder:r,busy:i}){return(0,W.jsxs)(`div`,{className:`relative`,children:[(0,W.jsx)(y,{className:`-translate-y-1/2 pointer-events-none absolute top-1/2 left-3 size-4 text-ink-4`}),(0,W.jsx)(`input`,{type:`search`,value:e,placeholder:r,onChange:e=>t(e.target.value),onKeyDown:e=>e.key===`Enter`&&n?.(),className:`h-9 w-full rounded-lg border border-input bg-card pr-3 pl-9 text-[0.875rem] text-ink outline-none transition placeholder:text-ink-4 focus:border-focus focus:ring-4 focus:ring-focus-glow`}),i?(0,W.jsx)(l,{className:`-translate-y-1/2 absolute top-1/2 right-3 size-4 text-ink-3`}):null]})}function Y({onFiles:e,accept:t,multiple:n=!0,className:r,children:i}){return(0,W.jsxs)(`label`,{onDragOver:e=>{e.preventDefault(),e.currentTarget.dataset.over=`1`},onDragLeave:e=>{delete e.currentTarget.dataset.over},onDrop:t=>{t.preventDefault(),delete t.currentTarget.dataset.over;let r=Array.from(t.dataTransfer.files);r.length&&e(n?r:r.slice(0,1))},className:u(`flex cursor-pointer items-center justify-center gap-2 rounded-lg border border-input border-dashed text-[0.875rem] text-ink-3 transition focus-within:border-focus focus-within:ring-4 focus-within:ring-focus-glow hover:border-ink-4 hover:text-ink data-[over]:border-focus data-[over]:bg-paper-2 data-[over]:text-ink`,r),children:[i,(0,W.jsx)(`input`,{className:`sr-only`,type:`file`,accept:t,multiple:n,onChange:t=>{let n=Array.from(t.target.files??[]);t.target.value=``,n.length&&e(n)}})]})}var X=`mt-1.5 text-[0.8125rem] text-ink-3`;function Z(e){let t=i(),[n,r]=(0,I.useState)(!1),a=E({mutationFn:e=>v.post(`/api/studio/account/link`,e),onSuccess:({url:e})=>{k(e),r(!0)}});return(0,I.useEffect)(()=>{if(!n)return;let e=setInterval(()=>void t.invalidateQueries({queryKey:[`me`]}),2e3),i=setTimeout(()=>r(!1),3e5);return()=>{clearInterval(e),clearTimeout(i)}},[n,t]),(0,I.useEffect)(()=>{e&&r(!1)},[e]),{link:a,waiting:n}}function Q({link:e,waiting:t}){return e.isError?(0,W.jsx)(`p`,{className:`text-[0.8125rem] text-rose`,children:f(`local.accountFailed`)}):t?(0,W.jsxs)(`p`,{className:`flex items-center gap-2 text-[0.8125rem] text-ink-3`,children:[(0,W.jsx)(l,{className:`size-3.5`}),` `,f(`local.accountWaiting`)]}):null}function ne(){let e=Z(!1),{link:t}=e,[n,r]=(0,I.useState)(``);return(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex items-start gap-4 py-5 first:pt-0 last:pb-0`,children:[(0,W.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-full bg-paper-2 text-ink-2`,children:(0,W.jsx)(j,{className:`size-5`})}),(0,W.jsxs)(`div`,{className:`min-w-0`,children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.local`)}),(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-relaxed`,children:f(`account.localText`)})]})]}),w.account?(0,W.jsxs)(`div`,{className:`flex flex-col gap-4 py-5 last:pb-0`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.with`)}),(0,W.jsxs)(`ul`,{className:`mt-2 flex flex-col gap-2 text-[0.875rem] text-ink-2 leading-snug`,children:[(0,W.jsxs)(`li`,{className:`flex items-start gap-2.5`,children:[(0,W.jsx)(b,{className:`mt-0.5 size-4 shrink-0 text-amber`}),f(`account.withCredits`)]}),(0,W.jsxs)(`li`,{className:`flex items-start gap-2.5`,children:[(0,W.jsx)(O,{className:`mt-0.5 size-4 shrink-0 text-cobalt`}),f(`account.withCloud`)]})]})]}),(0,W.jsx)(`div`,{children:(0,W.jsx)(_,{busy:t.isPending&&!t.variables?.signup,onClick:()=>t.mutate({}),children:f(`account.signIn`)})})]}):null,w.account?(0,W.jsxs)(`form`,{className:`flex flex-col gap-3 py-5 last:pb-0`,onSubmit:e=>{e.preventDefault(),t.mutate({signup:!0,code:n.trim()||void 0})},children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.new`)}),(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-relaxed`,children:f(`account.newHint`)})]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,W.jsx)(g,{value:n,maxLength:64,autoComplete:`off`,spellCheck:!1,placeholder:f(`account.code`),"aria-label":f(`account.code`),onChange:e=>r(e.target.value),className:`w-56 font-mono text-[0.875rem]`}),(0,W.jsx)(_,{type:`submit`,variant:`secondary`,className:`h-11`,busy:t.isPending&&!!t.variables?.signup,children:f(`account.create`)})]}),(0,W.jsx)(Q,{...e})]}):null]})}var $={start:`account.kind.start`,monthly:`account.kind.monthly`,gift:`account.kind.gift`};function re({account:e}){let t=i(),n=Z(e.signedIn),r=E({mutationFn:()=>v.del(`/api/studio/account`),onSuccess:()=>t.invalidateQueries({queryKey:[`me`]})}),a=new Intl.DateTimeFormat(p,{dateStyle:`medium`});return(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3 py-5 first:pt-0`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-medium text-[0.9375rem]`,children:e.name||e.email}),e.signedIn?(0,W.jsx)(h,{tone:`live`,children:f(`account.linked`)}):null]}),(0,W.jsx)(`div`,{className:`truncate text-[0.875rem] text-ink-3`,children:e.email})]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(e.url),children:[f(`setup.openAccount`),` `,(0,W.jsx)(x,{className:`size-4`})]}),(0,W.jsxs)(_,{variant:`ghost`,busy:r.isPending,onClick:()=>r.mutate(),children:[(0,W.jsx)(D,{className:`size-4`}),` `,f(`nav.logout`)]})]})]}),e.signedIn?null:(0,W.jsxs)(`div`,{className:`flex flex-col gap-3 py-5`,children:[(0,W.jsx)(`p`,{className:`text-[0.875rem] text-ink-2`,children:f(`local.accountExpired`)}),(0,W.jsx)(`div`,{children:(0,W.jsx)(_,{busy:n.link.isPending,onClick:()=>n.link.mutate({}),children:f(`account.signInAgain`)})}),(0,W.jsx)(Q,{...n})]}),e.credits===null?null:(0,W.jsxs)(`div`,{className:`py-5`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsx)(`div`,{className:`text-[0.8125rem] text-ink-3`,children:f(`account.credits`)}),(0,W.jsx)(`div`,{className:`font-display font-semibold text-[1.375rem] tabular-nums leading-tight`,children:f(`nav.credits`,{n:Math.floor(e.credits).toLocaleString()})})]}),(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(`${e.url}/billing`),children:[f(`account.topUp`),` `,(0,W.jsx)(x,{className:`size-4`})]})]}),e.expiring.length?(0,W.jsx)(`ul`,{className:`mt-3 flex flex-col gap-1 text-[0.8125rem] text-ink-3 tabular-nums`,children:e.expiring.map(e=>(0,W.jsxs)(`li`,{children:[f(`account.expires`,{n:Math.floor(e.credits).toLocaleString(),date:a.format(new Date(e.expiresAt))}),$[e.kind]?(0,W.jsxs)(`span`,{className:`text-ink-4`,children:[` · `,f($[e.kind])]}):null]},`${e.kind}:${e.expiresAt}`))}):null]}),(0,W.jsxs)(`div`,{className:`flex items-start gap-2.5 py-5 text-[0.875rem] text-ink-2 leading-snug last:pb-0`,children:[(0,W.jsx)(O,{className:`mt-0.5 size-4 shrink-0 text-cobalt`}),(0,W.jsx)(`p`,{children:f(`account.cloud`,{host:C(e.cloudUrl)})})]})]})}function ie({me:e,fromAccount:t}){let n=i(),[r,a]=(0,I.useState)(e.profile),o=e=>a(t=>({...t,...e})),s=H(r,async e=>{await v.put(`/api/studio/profile`,e),await n.invalidateQueries({queryKey:[`me`]})});return(0,W.jsx)(K,{title:f(`account.profile`),hint:f(`account.hint`),save:s,children:(0,W.jsxs)(`div`,{className:`flex flex-col gap-6 sm:flex-row sm:gap-8`,children:[(0,W.jsxs)(`div`,{className:`flex shrink-0 flex-col items-center gap-2 sm:w-32`,children:[(0,W.jsx)(`div`,{className:`flex size-20 items-center justify-center overflow-hidden rounded-full bg-ember-tint font-semibold text-[1.75rem] text-ember-strong ring-1 ring-border-soft`,children:e.user.image?(0,W.jsx)(`img`,{src:e.user.image,alt:``,className:`size-full object-cover`}):T(r.name)||`?`}),(0,W.jsx)(`p`,{className:`text-center text-[0.75rem] text-ink-3 leading-snug`,children:f(`account.initials`)})]}),(0,W.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-5`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.name`)}),(0,W.jsx)(g,{value:r.name,maxLength:80,disabled:t,onChange:e=>o({name:e.target.value})}),(0,W.jsx)(`p`,{className:X,children:f(t?`account.fromAccount`:`account.nameHint`)})]}),(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.about`)}),(0,W.jsx)(d,{minRows:3,maxLength:2e3,value:r.about,onChange:e=>o({about:e.target.value})}),(0,W.jsx)(`p`,{className:X,children:f(`account.aboutHint`)})]}),(0,W.jsxs)(`div`,{className:`grid gap-5 sm:grid-cols-2`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.email`)}),(0,W.jsx)(g,{type:`email`,value:r.email,maxLength:200,disabled:t,onChange:e=>o({email:e.target.value})})]}),(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.phone`)}),(0,W.jsx)(g,{type:`tel`,value:r.phone,maxLength:40,onChange:e=>o({phone:e.target.value})})]})]})]})]})})}function ae({me:e}){let t=e.mode===`managed`,n=t||!!e.account;return(0,W.jsxs)(`div`,{className:`flex flex-col gap-9`,children:[(0,W.jsx)(K,{title:f(`account.connection`),hint:f(`account.connectionHint`),children:t?(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-medium text-[0.9375rem]`,children:e.user.name}),(0,W.jsx)(h,{tone:`live`,children:f(`account.linked`)})]}),(0,W.jsx)(`div`,{className:`truncate text-[0.875rem] text-ink-3`,children:e.user.email})]}),e.manageUrl?(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(`${e.manageUrl}/account`),children:[f(`setup.openAccount`),` `,(0,W.jsx)(x,{className:`size-4`})]}):null]}):e.account?(0,W.jsx)(re,{account:e.account}):(0,W.jsx)(ne,{})}),(0,W.jsx)(ie,{me:e,fromAccount:n},n?`account`:`own`),(0,W.jsx)(K,{title:f(`account.look`),hint:f(`account.lookHint`),children:(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-4 pb-4`,children:[(0,W.jsx)(`span`,{className:`font-medium text-[0.875rem]`,children:f(`nav.language`)}),(0,W.jsx)(S,{tone:`surface`})]}),(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-4 pt-4`,children:[(0,W.jsx)(`span`,{className:`font-medium text-[0.875rem]`,children:f(`nav.theme`)}),(0,W.jsx)(te,{})]})]})})]})}export{Y as a,K as c,H as d,B as f,N as h,G as i,U as l,R as m,Q as n,q as o,V as p,Z as r,J as s,ae as t,z as u};
1
+ import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{D as r,Q as i}from"./surface-CywgBXMy.js";import{D as a,G as o,H as s,c,f as l,g as u,h as d,j as f,k as p,n as ee,o as m,r as h,s as g,t as _,x as v}from"./ui-DyazyiaK.js";import{n as y,r as b}from"./upload-Dl_w8YOa.js";import{t as x}from"./external-link-CbxUCKS8.js";import{B as te,H as S,I as C,U as w,W as T,_t as E,at as D,ft as O}from"./index-Dzs5btCG.js";import{n as k}from"./LocalRuntime-FTYk-ibA.js";var A={name:`hard-drive`,size:24,node:[[`path`,{d:`M10 16h.01`,key:`1bzywj`}],[`path`,{d:`M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`18tbho`}],[`path`,{d:`M21.946 12.013H2.054`,key:`zqlbp7`}],[`path`,{d:`M6 16h.01`,key:`1pmjb7`}]]};A.node;var j=o(A),M={name:`layout-grid`,size:24,node:[[`rect`,{width:`7`,height:`7`,x:`3`,y:`3`,rx:`1`,key:`1g98yp`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`3`,rx:`1`,key:`6d4xhi`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`14`,rx:`1`,key:`nxv5o0`}],[`rect`,{width:`7`,height:`7`,x:`3`,y:`14`,rx:`1`,key:`1bb6yr`}]]};M.node;var N=o(M),P={name:`list`,size:24,node:[[`path`,{d:`M3 5h.01`,key:`18ugdj`}],[`path`,{d:`M3 12h.01`,key:`nlz23k`}],[`path`,{d:`M3 19h.01`,key:`noohij`}],[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M8 12h13`,key:`1za7za`}],[`path`,{d:`M8 19h13`,key:`m83p4d`}]]};P.node;var F=o(P),I=e(t(),1),L=e=>[`project-files`,e];function R(e){return r({queryKey:L(e),queryFn:()=>v.get(`/api/studio/projects/${e}/files`),refetchInterval:e=>e.state.data?.files.some(e=>e.status===`pending`)?2e3:!1})}function z(e,t){return a(`/api/studio/projects/${e}/files/${t}/content`)}function B(e,t=!1){let n=i(),[r,a]=(0,I.useState)(!1),[o,s]=(0,I.useState)(null),c=()=>n.invalidateQueries({queryKey:L(e)}),l=async e=>{s(null);try{await e()}catch(e){s(e.message)}finally{await c()}};return{busy:r,error:o,readOnly:t,upload:async(t,n)=>{a(!0),await l(async()=>{for(let r of n)await v.upload(`/api/studio/projects/${e}/files?kind=${t}`,r),await c()}),a(!1)},describe:(t,n)=>l(()=>v.patch(`/api/studio/projects/${e}/files/${t}`,{description:n})),remove:t=>l(()=>v.del(`/api/studio/projects/${e}/files/${t}`)),reindex:t=>l(()=>v.post(`/api/studio/projects/${e}/files/${t}/reindex`)),order:(t,n)=>l(()=>v.put(`/api/studio/projects/${e}/files/order`,{kind:t,ids:n}))}}function V(e,t){let n=`wz.layout.${e}`,[r,i]=(0,I.useState)(()=>{try{let e=localStorage.getItem(n);return e===`list`||e===`cards`?e:t}catch{return t}});return[r,()=>i(e=>{let t=e===`list`?`cards`:`list`;try{localStorage.setItem(n,t)}catch{}return t})]}function H(e,t,n=700){let[r,i]=(0,I.useState)(`idle`),[a,o]=(0,I.useState)(null),s=JSON.stringify(e),c=(0,I.useRef)(s),l=(0,I.useRef)({value:e,json:s,save:t});l.current={value:e,json:s,save:t};let u=(0,I.useRef)(Promise.resolve()),d=(0,I.useCallback)(()=>{let e=l.current;e.json!==c.current&&(c.current=e.json,i(`saving`),u.current=u.current.then(async()=>{try{await e.save(e.value),o(null),i(`saved`)}catch(e){c.current=``,o(e.message),i(`error`)}}))},[]);return(0,I.useEffect)(()=>{if(s===c.current)return;let e=setTimeout(d,n);return()=>clearTimeout(e)},[s,n,d]),(0,I.useEffect)(()=>d,[d]),{state:r,error:a}}function U(e){return e<1e6?`${Math.max(1,Math.round(e/1e3))} KB`:`${(e/1e6).toFixed(1)} MB`}var W=e(n(),1);function G({id:e,children:t}){return(0,W.jsx)(`div`,{id:e,className:`scroll-mt-24 max-md:scroll-mt-36`,children:t})}function K({title:e,hint:t,save:n,action:r,locked:i,plain:a,children:o}){return(0,W.jsxs)(`section`,{className:`flex flex-col gap-2.5`,children:[(0,W.jsxs)(`div`,{className:`flex items-start justify-between gap-4 px-1`,children:[(0,W.jsxs)(`div`,{className:`min-w-0`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,W.jsx)(`h2`,{className:`font-display font-semibold text-lg leading-tight`,children:e}),n?.state===`saving`?(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-[0.75rem] text-ink-3`,children:[(0,W.jsx)(l,{className:`size-3`}),` `,f(`project.saving`)]}):n?.state===`saved`?(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-[0.75rem] text-moss`,children:[(0,W.jsx)(s,{className:`size-3.5`}),` `,f(`settings.saved`)]}):null]}),t?(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-snug`,children:t}):null]}),r?(0,W.jsx)(`div`,{className:`shrink-0`,children:r}):null]}),a?o:(0,W.jsxs)(ee,{className:`p-3.5 sm:p-5`,children:[i?(0,W.jsx)(`fieldset`,{disabled:!0,className:`min-w-0`,children:o}):o,n?.state===`error`&&n.error?(0,W.jsx)(`p`,{className:`mt-4 text-[0.875rem] text-rose`,children:n.error}):null]})]})}function q({children:e,layout:t,onToggle:n}){return(0,W.jsxs)(`div`,{className:`mb-3 flex items-start gap-2`,children:[(0,W.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,W.jsx)(`div`,{className:`w-56 max-w-full transition-[width] duration-200 focus-within:w-full has-[input:not(:placeholder-shown)]:w-full`,children:e})}),(0,W.jsx)(m,{label:f(t===`list`?`project.viewCards`:`project.viewList`),onClick:n,children:t===`list`?(0,W.jsx)(N,{className:`size-4`}):(0,W.jsx)(F,{className:`size-4`})})]})}function J({value:e,onChange:t,onEnter:n,placeholder:r,busy:i}){return(0,W.jsxs)(`div`,{className:`relative`,children:[(0,W.jsx)(y,{className:`-translate-y-1/2 pointer-events-none absolute top-1/2 left-3 size-4 text-ink-4`}),(0,W.jsx)(`input`,{type:`search`,value:e,placeholder:r,onChange:e=>t(e.target.value),onKeyDown:e=>e.key===`Enter`&&n?.(),className:`h-9 w-full rounded-lg border border-input bg-card pr-3 pl-9 text-[0.875rem] text-ink outline-none transition placeholder:text-ink-4 focus:border-focus focus:ring-4 focus:ring-focus-glow`}),i?(0,W.jsx)(l,{className:`-translate-y-1/2 absolute top-1/2 right-3 size-4 text-ink-3`}):null]})}function Y({onFiles:e,accept:t,multiple:n=!0,className:r,children:i}){return(0,W.jsxs)(`label`,{onDragOver:e=>{e.preventDefault(),e.currentTarget.dataset.over=`1`},onDragLeave:e=>{delete e.currentTarget.dataset.over},onDrop:t=>{t.preventDefault(),delete t.currentTarget.dataset.over;let r=Array.from(t.dataTransfer.files);r.length&&e(n?r:r.slice(0,1))},className:u(`flex cursor-pointer items-center justify-center gap-2 rounded-lg border border-input border-dashed text-[0.875rem] text-ink-3 transition focus-within:border-focus focus-within:ring-4 focus-within:ring-focus-glow hover:border-ink-4 hover:text-ink data-[over]:border-focus data-[over]:bg-paper-2 data-[over]:text-ink`,r),children:[i,(0,W.jsx)(`input`,{className:`sr-only`,type:`file`,accept:t,multiple:n,onChange:t=>{let n=Array.from(t.target.files??[]);t.target.value=``,n.length&&e(n)}})]})}var X=`mt-1.5 text-[0.8125rem] text-ink-3`;function Z(e){let t=i(),[n,r]=(0,I.useState)(!1),a=E({mutationFn:e=>v.post(`/api/studio/account/link`,e),onSuccess:({url:e})=>{k(e),r(!0)}});return(0,I.useEffect)(()=>{if(!n)return;let e=setInterval(()=>void t.invalidateQueries({queryKey:[`me`]}),2e3),i=setTimeout(()=>r(!1),3e5);return()=>{clearInterval(e),clearTimeout(i)}},[n,t]),(0,I.useEffect)(()=>{e&&r(!1)},[e]),{link:a,waiting:n}}function Q({link:e,waiting:t}){return e.isError?(0,W.jsx)(`p`,{className:`text-[0.8125rem] text-rose`,children:f(`local.accountFailed`)}):t?(0,W.jsxs)(`p`,{className:`flex items-center gap-2 text-[0.8125rem] text-ink-3`,children:[(0,W.jsx)(l,{className:`size-3.5`}),` `,f(`local.accountWaiting`)]}):null}function ne(){let e=Z(!1),{link:t}=e,[n,r]=(0,I.useState)(``);return(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex items-start gap-4 py-5 first:pt-0 last:pb-0`,children:[(0,W.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-full bg-paper-2 text-ink-2`,children:(0,W.jsx)(j,{className:`size-5`})}),(0,W.jsxs)(`div`,{className:`min-w-0`,children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.local`)}),(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-relaxed`,children:f(`account.localText`)})]})]}),w.account?(0,W.jsxs)(`div`,{className:`flex flex-col gap-4 py-5 last:pb-0`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.with`)}),(0,W.jsxs)(`ul`,{className:`mt-2 flex flex-col gap-2 text-[0.875rem] text-ink-2 leading-snug`,children:[(0,W.jsxs)(`li`,{className:`flex items-start gap-2.5`,children:[(0,W.jsx)(b,{className:`mt-0.5 size-4 shrink-0 text-amber`}),f(`account.withCredits`)]}),(0,W.jsxs)(`li`,{className:`flex items-start gap-2.5`,children:[(0,W.jsx)(O,{className:`mt-0.5 size-4 shrink-0 text-cobalt`}),f(`account.withCloud`)]})]})]}),(0,W.jsx)(`div`,{children:(0,W.jsx)(_,{busy:t.isPending&&!t.variables?.signup,onClick:()=>t.mutate({}),children:f(`account.signIn`)})})]}):null,w.account?(0,W.jsxs)(`form`,{className:`flex flex-col gap-3 py-5 last:pb-0`,onSubmit:e=>{e.preventDefault(),t.mutate({signup:!0,code:n.trim()||void 0})},children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.new`)}),(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-relaxed`,children:f(`account.newHint`)})]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,W.jsx)(g,{value:n,maxLength:64,autoComplete:`off`,spellCheck:!1,placeholder:f(`account.code`),"aria-label":f(`account.code`),onChange:e=>r(e.target.value),className:`w-56 font-mono text-[0.875rem]`}),(0,W.jsx)(_,{type:`submit`,variant:`secondary`,className:`h-11`,busy:t.isPending&&!!t.variables?.signup,children:f(`account.create`)})]}),(0,W.jsx)(Q,{...e})]}):null]})}var $={start:`account.kind.start`,monthly:`account.kind.monthly`,gift:`account.kind.gift`};function re({account:e}){let t=i(),n=Z(e.signedIn),r=E({mutationFn:()=>v.del(`/api/studio/account`),onSuccess:()=>t.invalidateQueries({queryKey:[`me`]})}),a=new Intl.DateTimeFormat(p,{dateStyle:`medium`});return(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3 py-5 first:pt-0`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-medium text-[0.9375rem]`,children:e.name||e.email}),e.signedIn?(0,W.jsx)(h,{tone:`live`,children:f(`account.linked`)}):null]}),(0,W.jsx)(`div`,{className:`truncate text-[0.875rem] text-ink-3`,children:e.email})]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(e.url),children:[f(`setup.openAccount`),` `,(0,W.jsx)(x,{className:`size-4`})]}),(0,W.jsxs)(_,{variant:`ghost`,busy:r.isPending,onClick:()=>r.mutate(),children:[(0,W.jsx)(D,{className:`size-4`}),` `,f(`nav.logout`)]})]})]}),e.signedIn?null:(0,W.jsxs)(`div`,{className:`flex flex-col gap-3 py-5`,children:[(0,W.jsx)(`p`,{className:`text-[0.875rem] text-ink-2`,children:f(`local.accountExpired`)}),(0,W.jsx)(`div`,{children:(0,W.jsx)(_,{busy:n.link.isPending,onClick:()=>n.link.mutate({}),children:f(`account.signInAgain`)})}),(0,W.jsx)(Q,{...n})]}),e.credits===null?null:(0,W.jsxs)(`div`,{className:`py-5`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsx)(`div`,{className:`text-[0.8125rem] text-ink-3`,children:f(`account.credits`)}),(0,W.jsx)(`div`,{className:`font-display font-semibold text-[1.375rem] tabular-nums leading-tight`,children:f(`nav.credits`,{n:Math.floor(e.credits).toLocaleString()})})]}),(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(`${e.url}/billing`),children:[f(`account.topUp`),` `,(0,W.jsx)(x,{className:`size-4`})]})]}),e.expiring.length?(0,W.jsx)(`ul`,{className:`mt-3 flex flex-col gap-1 text-[0.8125rem] text-ink-3 tabular-nums`,children:e.expiring.map(e=>(0,W.jsxs)(`li`,{children:[f(`account.expires`,{n:Math.floor(e.credits).toLocaleString(),date:a.format(new Date(e.expiresAt))}),$[e.kind]?(0,W.jsxs)(`span`,{className:`text-ink-4`,children:[` · `,f($[e.kind])]}):null]},`${e.kind}:${e.expiresAt}`))}):null]}),(0,W.jsxs)(`div`,{className:`flex items-start gap-2.5 py-5 text-[0.875rem] text-ink-2 leading-snug last:pb-0`,children:[(0,W.jsx)(O,{className:`mt-0.5 size-4 shrink-0 text-cobalt`}),(0,W.jsx)(`p`,{children:f(`account.cloud`,{host:C(e.cloudUrl)})})]})]})}function ie({me:e,fromAccount:t}){let n=i(),[r,a]=(0,I.useState)(e.profile),o=e=>a(t=>({...t,...e})),s=H(r,async e=>{await v.put(`/api/studio/profile`,e),await n.invalidateQueries({queryKey:[`me`]})});return(0,W.jsx)(K,{title:f(`account.profile`),hint:f(`account.hint`),save:s,children:(0,W.jsxs)(`div`,{className:`flex flex-col gap-6 sm:flex-row sm:gap-8`,children:[(0,W.jsxs)(`div`,{className:`flex shrink-0 flex-col items-center gap-2 sm:w-32`,children:[(0,W.jsx)(`div`,{className:`flex size-20 items-center justify-center overflow-hidden rounded-full bg-ember-tint font-semibold text-[1.75rem] text-ember-strong ring-1 ring-border-soft`,children:e.user.image?(0,W.jsx)(`img`,{src:e.user.image,alt:``,className:`size-full object-cover`}):T(r.name)||`?`}),(0,W.jsx)(`p`,{className:`text-center text-[0.75rem] text-ink-3 leading-snug`,children:f(`account.initials`)})]}),(0,W.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-5`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.name`)}),(0,W.jsx)(g,{value:r.name,maxLength:80,disabled:t,onChange:e=>o({name:e.target.value})}),(0,W.jsx)(`p`,{className:X,children:f(t?`account.fromAccount`:`account.nameHint`)})]}),(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.about`)}),(0,W.jsx)(d,{minRows:3,maxLength:2e3,value:r.about,onChange:e=>o({about:e.target.value})}),(0,W.jsx)(`p`,{className:X,children:f(`account.aboutHint`)})]}),(0,W.jsxs)(`div`,{className:`grid gap-5 sm:grid-cols-2`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.email`)}),(0,W.jsx)(g,{type:`email`,value:r.email,maxLength:200,disabled:t,onChange:e=>o({email:e.target.value})})]}),(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.phone`)}),(0,W.jsx)(g,{type:`tel`,value:r.phone,maxLength:40,onChange:e=>o({phone:e.target.value})})]})]})]})]})})}function ae({me:e}){let t=e.mode===`managed`,n=t||!!e.account;return(0,W.jsxs)(`div`,{className:`flex flex-col gap-9`,children:[(0,W.jsx)(K,{title:f(`account.connection`),hint:f(`account.connectionHint`),children:t?(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-medium text-[0.9375rem]`,children:e.user.name}),(0,W.jsx)(h,{tone:`live`,children:f(`account.linked`)})]}),(0,W.jsx)(`div`,{className:`truncate text-[0.875rem] text-ink-3`,children:e.user.email})]}),e.manageUrl?(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(`${e.manageUrl}/account`),children:[f(`setup.openAccount`),` `,(0,W.jsx)(x,{className:`size-4`})]}):null]}):e.account?(0,W.jsx)(re,{account:e.account}):(0,W.jsx)(ne,{})}),(0,W.jsx)(ie,{me:e,fromAccount:n},n?`account`:`own`),(0,W.jsx)(K,{title:f(`account.look`),hint:f(`account.lookHint`),children:(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-4 pb-4`,children:[(0,W.jsx)(`span`,{className:`font-medium text-[0.875rem]`,children:f(`nav.language`)}),(0,W.jsx)(S,{tone:`surface`})]}),(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-4 pt-4`,children:[(0,W.jsx)(`span`,{className:`font-medium text-[0.875rem]`,children:f(`nav.theme`)}),(0,W.jsx)(te,{})]})]})})]})}export{Y as a,K as c,H as d,B as f,N as h,G as i,U as l,R as m,Q as n,q as o,V as p,Z as r,J as s,ae as t,z as u};
@@ -1 +1 @@
1
- import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{t as r}from"./preload-helper-CNEI7N0N.js";import{a as i,f as a,g as o,i as s,j as c,s as l}from"./ui-DyazyiaK.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/,``):c(`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-tH5O-JCg.js`);return{default:e}},[])).default}function v({open:e,onClose:t,version:n}){let[r,v]=(0,u.useState)(null),[y,b]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||r)return;let t=!1;return _(n).then(e=>{t||v(e)}),()=>{t=!0}},[e,r,n]),(0,u.useEffect)(()=>{e||b(``)},[e]);let x=r?g(r,y):[];return(0,d.jsxs)(s,{open:e,onClose:t,title:c(`about.changelog`),wide:!0,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:c(`about.changelogHint`)}),r===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(a,{})}):r.length===0?(0,d.jsx)(i,{children:c(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(l,{type:`search`,value:y,placeholder:c(`about.search`),onChange:e=>b(e.target.value)}),x.length===0?(0,d.jsx)(i,{children:c(`about.noMatches`)}):null,x.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)(`ul`,{className:`mt-3 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:c(`about.breaking`)}):null]})]},e.id)})})]},e.version??`unreleased`))]})]})}export{v as ChangelogDialog};
1
+ import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{t as r}from"./preload-helper-CNEI7N0N.js";import{a as i,f as a,g as o,i as s,j as c,s as l}from"./ui-DyazyiaK.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/,``):c(`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-B6AlU2mc.js`);return{default:e}},[])).default}function v({open:e,onClose:t,version:n}){let[r,v]=(0,u.useState)(null),[y,b]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||r)return;let t=!1;return _(n).then(e=>{t||v(e)}),()=>{t=!0}},[e,r,n]),(0,u.useEffect)(()=>{e||b(``)},[e]);let x=r?g(r,y):[];return(0,d.jsxs)(s,{open:e,onClose:t,title:c(`about.changelog`),wide:!0,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:c(`about.changelogHint`)}),r===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(a,{})}):r.length===0?(0,d.jsx)(i,{children:c(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(l,{type:`search`,value:y,placeholder:c(`about.search`),onChange:e=>b(e.target.value)}),x.length===0?(0,d.jsx)(i,{children:c(`about.noMatches`)}):null,x.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)(`ul`,{className:`mt-3 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:c(`about.breaking`)}):null]})]},e.id)})})]},e.version??`unreleased`))]})]})}export{v as ChangelogDialog};