sv 0.16.5 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
- import { AGENTS, COMMANDS, Walker, coerceVersion, color, constructCommand, createPrinter, dedent, defineEnv, detect, downloadJson, fileExists, isVersionUnsupportedBelow, js, loadFile, loadPackageJson, minVersion, parse, pnpm, resolveCommand, resolveCommandArray, sanitizeName, saveFile, svelte, svelteConfig, transforms } from "@sveltejs/sv-utils";
2
+ import { AGENTS, COMMANDS, KIT3_TSCONFIG, KIT3_TSCONFIG_DEFAULT, Walker, coerceVersion, color, constructCommand, createPrinter, dedent, defineEnv, detect, downloadJson, fileExists, isKit3, isVersionUnsupportedBelow, js, libSubpathImports, loadFile, loadPackageJson, minVersion, parse, pnpm, resolveCommand, resolveCommandArray, resolveLibPrefix, sanitizeName, saveFile, svelte, svelteConfig, transforms } from "@sveltejs/sv-utils";
3
3
  import fs, { closeSync, existsSync, openSync, readSync, statSync } from "node:fs";
4
4
  import path, { basename, delimiter, dirname, isAbsolute, join, normalize, resolve } from "node:path";
5
5
  import { promisify, stripVTControlCharacters, styleText } from "node:util";
@@ -8,7 +8,7 @@ import * as b$1 from "node:readline";
8
8
  import G from "node:readline";
9
9
  import { ReadStream } from "node:tty";
10
10
  import { fileURLToPath } from "node:url";
11
- import childProcess, { exec, spawn } from "node:child_process";
11
+ import childProcess, { exec, spawn, spawnSync } from "node:child_process";
12
12
  import { pipeline } from "node:stream/promises";
13
13
  import { PassThrough } from "node:stream";
14
14
  import { EventEmitter } from "node:events";
@@ -493,9 +493,9 @@ function W({ input: r = stdin, output: t = stdout, overwrite: s = !0, hideCursor
493
493
  r.off("keypress", n), e && t.write(import_src.cursor.show), r instanceof ReadStream && r.isTTY && !q$1 && r.setRawMode(!1), i.terminal = !1, i.close();
494
494
  };
495
495
  }
496
- const A = (r) => "columns" in r && typeof r.columns == "number" ? r.columns : 80, L = (r) => "rows" in r && typeof r.rows == "number" ? r.rows : 20;
497
- function B(r, t, s, e = s, i = s, n) {
498
- return wrapAnsi(t, A(r ?? stdout) - s.length, {
496
+ const A$1 = (r) => "columns" in r && typeof r.columns == "number" ? r.columns : 80, L$1 = (r) => "rows" in r && typeof r.rows == "number" ? r.rows : 20;
497
+ function B$1(r, t, s, e = s, i = s, n) {
498
+ return wrapAnsi(t, A$1(r ?? stdout) - s.length, {
499
499
  hard: !0,
500
500
  trim: !1
501
501
  }).split(`
@@ -629,7 +629,7 @@ var m = class {
629
629
  if (t !== this._prevFrame) {
630
630
  if (this.state === "initial") this.output.write(import_src.cursor.hide);
631
631
  else {
632
- const s = Y$1(this._prevFrame, t), e = L(this.output);
632
+ const s = Y$1(this._prevFrame, t), e = L$1(this.output);
633
633
  if (this.restoreCursor(), s) {
634
634
  const i = Math.max(0, s.numLinesAfter - e), n = Math.max(0, s.numLinesBefore - e);
635
635
  let o = s.lines.find((u) => u >= i);
@@ -805,7 +805,7 @@ const tt = se(), at = () => process.env.CI === "true", Tt = (t) => t.isTTY === !
805
805
  removals: c
806
806
  };
807
807
  }, F$1 = ({ cursor: t, options: i, style: s, output: r = process.stdout, maxItems: u = Number.POSITIVE_INFINITY, columnPadding: n = 0, rowPadding: a = 4 }) => {
808
- const c = A(r) - n, o = L(r), l = styleText("dim", "..."), d = Math.max(o - a, 0), g = Math.max(Math.min(u, d), 5);
808
+ const c = A$1(r) - n, o = L$1(r), l = styleText("dim", "..."), d = Math.max(o - a, 0), g = Math.max(Math.min(u, d), 5);
809
809
  let p = 0;
810
810
  t >= g - 3 && (p = Math.max(Math.min(t - g + 3, i.length - g), 0));
811
811
  let f = g < i.length && p > 0, h = g < i.length && p + g < i.length;
@@ -843,7 +843,7 @@ const le = (t) => {
843
843
  output: t.output,
844
844
  initialValue: t.initialValue ?? !0,
845
845
  render() {
846
- const r = t.withGuide ?? h$1.withGuide, u = `${P$1(this.state)} `, n = r ? `${styleText("gray", $)} ` : "", a = B(t.output, t.message, n, u), c = `${r ? `${styleText("gray", $)}
846
+ const r = t.withGuide ?? h$1.withGuide, u = `${P$1(this.state)} `, n = r ? `${styleText("gray", $)} ` : "", a = B$1(t.output, t.message, n, u), c = `${r ? `${styleText("gray", $)}
847
847
  ` : ""}${a}
848
848
  `, o = this.value ? i : s;
849
849
  switch (this.state) {
@@ -961,7 +961,7 @@ ${styleText("reset", styleText("dim", `Press ${styleText([
961
961
  ], " space ")} to select, ${styleText("gray", styleText("bgWhite", styleText("inverse", " enter ")))} to submit`))}`;
962
962
  },
963
963
  render() {
964
- const r = t.withGuide ?? h$1.withGuide, u = B(t.output, t.message, r ? `${ft(this.state)} ` : "", `${P$1(this.state)} `), n = `${r ? `${styleText("gray", $)}
964
+ const r = t.withGuide ?? h$1.withGuide, u = B$1(t.output, t.message, r ? `${ft(this.state)} ` : "", `${P$1(this.state)} `), n = `${r ? `${styleText("gray", $)}
965
965
  ` : ""}${u}
966
966
  `, a = this.value ?? [], c = (o, l) => {
967
967
  if (o.disabled) return i(o, "disabled");
@@ -971,12 +971,12 @@ ${styleText("reset", styleText("dim", `Press ${styleText([
971
971
  switch (this.state) {
972
972
  case "submit": {
973
973
  const o = this.options.filter(({ value: d }) => a.includes(d)).map((d) => i(d, "submitted")).join(styleText("dim", ", ")) || styleText("dim", "none");
974
- return `${n}${B(t.output, o, r ? `${styleText("gray", $)} ` : "")}`;
974
+ return `${n}${B$1(t.output, o, r ? `${styleText("gray", $)} ` : "")}`;
975
975
  }
976
976
  case "cancel": {
977
977
  const o = this.options.filter(({ value: d }) => a.includes(d)).map((d) => i(d, "cancelled")).join(styleText("dim", ", "));
978
978
  if (o.trim() === "") return `${n}${styleText("gray", $)}`;
979
- return `${n}${B(t.output, o, r ? `${styleText("gray", $)} ` : "")}${r ? `
979
+ return `${n}${B$1(t.output, o, r ? `${styleText("gray", $)} ` : "")}${r ? `
980
980
  ${styleText("gray", $)}` : ""}`;
981
981
  }
982
982
  case "error": {
@@ -1027,7 +1027,7 @@ ${r ? styleText("cyan", x$1) : ""}
1027
1027
  }, Ce = (t = "", i = "", s) => {
1028
1028
  const r = s?.output ?? V.stdout, u = s?.withGuide ?? h$1.withGuide, n = s?.format ?? be, a = [
1029
1029
  "",
1030
- ...Se(t, A(r) - 6, n).split(`
1030
+ ...Se(t, A$1(r) - 6, n).split(`
1031
1031
  `).map(n),
1032
1032
  ""
1033
1033
  ], c = fastStringWidth(i), o = Math.max(a.reduce((p, f) => {
@@ -1053,7 +1053,7 @@ ${styleText("gray", g + st.repeat(o + 2) + dt)}
1053
1053
  ], delay: a = tt ? 80 : 120, signal: c, ...o } = {}) => {
1054
1054
  const l = at();
1055
1055
  let d, g, p = !1, f = !1, h = "", I, m = performance.now();
1056
- const y = A(s), v = o?.styleFrame ?? _e, C = (_) => {
1056
+ const y = A$1(s), v = o?.styleFrame ?? _e, C = (_) => {
1057
1057
  const A = _ > 1 ? u ?? h$1.messages.error : r ?? h$1.messages.cancel;
1058
1058
  f = _ === 1, p && (W$1(A, _), f && typeof i == "function" && i());
1059
1059
  }, S = () => C(2), b = () => C(1), G = () => {
@@ -1136,17 +1136,17 @@ ${styleText("gray", g + st.repeat(o + 2) + dt)}
1136
1136
  output: t.output,
1137
1137
  initialValue: t.initialValue,
1138
1138
  render() {
1139
- const s = t.withGuide ?? h$1.withGuide, r = `${P$1(this.state)} `, u = `${ft(this.state)} `, n = B(t.output, t.message, u, r), a = `${s ? `${styleText("gray", $)}
1139
+ const s = t.withGuide ?? h$1.withGuide, r = `${P$1(this.state)} `, u = `${ft(this.state)} `, n = B$1(t.output, t.message, u, r), a = `${s ? `${styleText("gray", $)}
1140
1140
  ` : ""}${n}
1141
1141
  `;
1142
1142
  switch (this.state) {
1143
1143
  case "submit": {
1144
1144
  const c = s ? `${styleText("gray", $)} ` : "";
1145
- return `${a}${B(t.output, i(this.options[this.cursor], "selected"), c)}`;
1145
+ return `${a}${B$1(t.output, i(this.options[this.cursor], "selected"), c)}`;
1146
1146
  }
1147
1147
  case "cancel": {
1148
1148
  const c = s ? `${styleText("gray", $)} ` : "";
1149
- return `${a}${B(t.output, i(this.options[this.cursor], "cancelled"), c)}${s ? `
1149
+ return `${a}${B$1(t.output, i(this.options[this.cursor], "cancelled"), c)}${s ? `
1150
1150
  ${styleText("gray", $)}` : ""}`;
1151
1151
  }
1152
1152
  default: {
@@ -1192,7 +1192,7 @@ ${Bt}${r.trimStart()}`), s = 3 + stripVTControlCharacters(r.trimStart()).length)
1192
1192
  warning: (t) => q.warn(t),
1193
1193
  error: (t) => q.message(t, { symbol: styleText("red", yt) })
1194
1194
  }, Oe = (t) => t.replace(/\x1b\[(?:\d+;)*\d*[ABCDEFGHfJKSTsu]|\x1b\[(s|u)/g, ""), Pe = (t) => {
1195
- const i = t.output ?? process.stdout, s = A(i), r = styleText("gray", $), u = t.spacing ?? 1, n = 3, a = t.retainLog === !0, c = !at() && Tt(i);
1195
+ const i = t.output ?? process.stdout, s = A$1(i), r = styleText("gray", $), u = t.spacing ?? 1, n = 3, a = t.retainLog === !0, c = !at() && Tt(i);
1196
1196
  i.write(`${r}
1197
1197
  `), i.write(`${styleText("green", H)} ${t.title}
1198
1198
  `);
@@ -1348,7 +1348,7 @@ ${i ? styleText("cyan", x$1) : ""}
1348
1348
  //#endregion
1349
1349
  //#region package.json
1350
1350
  var name = "sv";
1351
- var version = "0.16.5";
1351
+ var version = "0.17.0";
1352
1352
  //#endregion
1353
1353
  //#region src/core/errors.ts
1354
1354
  var UnsupportedError = class extends Error {
@@ -1361,6 +1361,7 @@ var UnsupportedError = class extends Error {
1361
1361
  };
1362
1362
  //#endregion
1363
1363
  //#region src/core/common.ts
1364
+ const RX_IMPORT_ONLY = /^\s*@\S+\s*$/;
1364
1365
  const NO_PREFIX = "--no-";
1365
1366
  let options$8 = [];
1366
1367
  function getLongFlag(flags) {
@@ -1530,7 +1531,7 @@ function updateAgent(projectPath, language, packageManager, loadedAddons) {
1530
1531
  const agentFiles = [
1531
1532
  "AGENTS.md",
1532
1533
  "GEMINI.md",
1533
- "CLAUDE.md"
1534
+ ".claude/CLAUDE.md"
1534
1535
  ];
1535
1536
  const languageLabel = language === "typescript" ? "TypeScript" : language === "checkjs" ? "JavaScript (JSDoc)" : "None";
1536
1537
  const packageManagerLabel = packageManager ?? "npm";
@@ -1549,6 +1550,7 @@ function updateAgent(projectPath, language, packageManager, loadedAddons) {
1549
1550
  const agentPath = path.join(projectPath, fileName);
1550
1551
  if (!fs.existsSync(agentPath)) continue;
1551
1552
  let content = fs.readFileSync(agentPath, "utf-8");
1553
+ if (RX_IMPORT_ONLY.test(content)) continue;
1552
1554
  content = content.replace(existingSectionPattern, "");
1553
1555
  content = configSection + content;
1554
1556
  fs.writeFileSync(agentPath, content);
@@ -1885,10 +1887,12 @@ var k = class extends Error {
1885
1887
  this.output = t;
1886
1888
  }
1887
1889
  };
1890
+ const A = /\r?\n/;
1888
1891
  const j = {
1889
1892
  timeout: void 0,
1890
1893
  persist: false
1891
1894
  };
1895
+ const M = { timeout: void 0 };
1892
1896
  const N = { windowsHide: true };
1893
1897
  function P(e) {
1894
1898
  const t = new AbortController();
@@ -2036,12 +2040,56 @@ var I = class {
2036
2040
  if (this._resolveClose) this._resolveClose();
2037
2041
  };
2038
2042
  };
2043
+ function L(e, r, i) {
2044
+ const a = {
2045
+ ...M,
2046
+ ...i
2047
+ };
2048
+ const o = cwd();
2049
+ const s = {
2050
+ windowsHide: true,
2051
+ ...a.nodeOptions
2052
+ };
2053
+ if (a.timeout !== void 0) s.timeout = a.timeout;
2054
+ s.env = y(o, s.env, a.nodePath);
2055
+ const c = D(e, r ?? [], s);
2056
+ const l = spawnSync(c.command, c.args, c.options);
2057
+ if (l.error) throw l.error;
2058
+ const u = l.stdout?.toString() ?? "";
2059
+ const d = l.stderr?.toString() ?? "";
2060
+ const f = l.status ?? void 0;
2061
+ const p = l.signal != null;
2062
+ const m = {
2063
+ stdout: u,
2064
+ stderr: d,
2065
+ get exitCode() {
2066
+ return f;
2067
+ },
2068
+ get pid() {
2069
+ return l.pid;
2070
+ },
2071
+ get killed() {
2072
+ return p;
2073
+ },
2074
+ *[Symbol.iterator]() {
2075
+ for (const e of [u, d]) {
2076
+ if (!e) continue;
2077
+ const t = e.split(A);
2078
+ if (t[t.length - 1] === "") t.pop();
2079
+ yield* t;
2080
+ }
2081
+ }
2082
+ };
2083
+ if (a.throwOnError && f !== 0 && f !== void 0) throw new k(m, m);
2084
+ return m;
2085
+ }
2039
2086
  const R = (e, t, n) => {
2040
2087
  const r = new I(e, t, n);
2041
2088
  r.spawn();
2042
2089
  return r;
2043
2090
  };
2044
2091
  const z = R;
2092
+ const B = L;
2045
2093
  //#endregion
2046
2094
  //#region ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
2047
2095
  /**
@@ -5637,11 +5685,9 @@ function pipe(...pipe$1) {
5637
5685
  }
5638
5686
  //#endregion
5639
5687
  //#region src/core/config.ts
5640
- /**
5641
- * The entry point for your addon, It will hold every thing! (options, setup, run, nextSteps, ...)
5642
- */
5643
- function defineAddon(config) {
5644
- return config;
5688
+ function defineAddon(...args) {
5689
+ if (args.length === 0) return (config) => config;
5690
+ return args[0];
5645
5691
  }
5646
5692
  /**
5647
5693
  * Generates an inline error hint based on the addon source
@@ -5690,6 +5736,263 @@ function createOptionBuilder(options) {
5690
5736
  };
5691
5737
  }
5692
5738
  //#endregion
5739
+ //#region src/addons/ai-tools.ts
5740
+ const REGEX_MD = /\.md$/;
5741
+ const CLIENTS = {
5742
+ "claude-code": {
5743
+ label: "Claude Code",
5744
+ pluginSettings: {
5745
+ path: ".claude/settings.json",
5746
+ marketplace: "svelte",
5747
+ repo: "sveltejs/ai-tools",
5748
+ id: "svelte@svelte"
5749
+ },
5750
+ agentPath: "AGENTS.md",
5751
+ agentLink: {
5752
+ path: ".claude/CLAUDE.md",
5753
+ contents: "@../AGENTS.md\n"
5754
+ },
5755
+ configPath: ".mcp.json",
5756
+ skillsPath: ".claude/skills",
5757
+ agentsPath: ".claude/agents",
5758
+ mcpOptions: {
5759
+ typeLocal: "stdio",
5760
+ typeRemote: "http",
5761
+ env: true
5762
+ }
5763
+ },
5764
+ cursor: {
5765
+ label: "Cursor",
5766
+ agentPath: "AGENTS.md",
5767
+ configPath: ".cursor/mcp.json",
5768
+ skillsPath: ".cursor/skills",
5769
+ agentsPath: ".cursor/agents",
5770
+ mcpOptions: {}
5771
+ },
5772
+ gemini: {
5773
+ label: "Gemini",
5774
+ agentPath: "GEMINI.md",
5775
+ configPath: ".gemini/settings.json",
5776
+ skillsPath: ".gemini/skills",
5777
+ agentsPath: ".gemini/agents",
5778
+ schema: "https://raw.githubusercontent.com/google-gemini/gemini-cli/main/schemas/settings.schema.json",
5779
+ mcpOptions: {}
5780
+ },
5781
+ opencode: {
5782
+ label: "OpenCode",
5783
+ pluginOnly: true,
5784
+ agentPath: "AGENTS.md",
5785
+ configPath: ".opencode/opencode.json",
5786
+ schema: "https://opencode.ai/config.json",
5787
+ customData: { plugin: ["@sveltejs/opencode"] },
5788
+ extraFiles: [{
5789
+ path: ".opencode/svelte.json",
5790
+ data: { $schema: "https://svelte.dev/opencode/schema.json" }
5791
+ }]
5792
+ },
5793
+ vscode: {
5794
+ label: "VS Code",
5795
+ agentPath: "AGENTS.md",
5796
+ configPath: ".vscode/mcp.json",
5797
+ skillsPath: ".github/skills",
5798
+ agentsPath: ".github/agents",
5799
+ agentExtension: ".agent.md",
5800
+ mcpOptions: { serversKey: "servers" }
5801
+ },
5802
+ other: {
5803
+ label: "Other",
5804
+ agentPath: "AGENTS.md"
5805
+ }
5806
+ };
5807
+ const acceptsTools = (client) => Boolean(client && !client.pluginOnly && (client.skillsPath || client.agentsPath || client.configPath));
5808
+ const wantsLooseTools = (client, delivery) => acceptsTools(client) && (!client.pluginSettings || delivery !== "plugin");
5809
+ const wantsMcpConfig = (client, delivery) => Boolean(client?.mcpOptions) && wantsLooseTools(client, delivery);
5810
+ const TOOLS = {
5811
+ mcp: {
5812
+ label: "MCP server",
5813
+ kind: "mcp"
5814
+ },
5815
+ "svelte-code-writer": {
5816
+ label: "svelte-code-writer",
5817
+ kind: "skill",
5818
+ hint: "skill"
5819
+ },
5820
+ "svelte-core-bestpractices": {
5821
+ label: "svelte-core-bestpractices",
5822
+ kind: "skill",
5823
+ hint: "skill"
5824
+ },
5825
+ "svelte-file-editor": {
5826
+ label: "svelte-file-editor",
5827
+ kind: "agent",
5828
+ hint: "sub-agent"
5829
+ }
5830
+ };
5831
+ var ai_tools_default = defineAddon({
5832
+ id: "ai-tools",
5833
+ shortDescription: "Svelte AI tools",
5834
+ homepage: "https://svelte.dev/docs/ai",
5835
+ options: defineAddonOptions().add("ide", {
5836
+ question: "Which client would you like to use?",
5837
+ type: "multiselect",
5838
+ default: [],
5839
+ options: Object.entries(CLIENTS).map(([value, client]) => ({
5840
+ value,
5841
+ label: client.label
5842
+ })),
5843
+ required: true
5844
+ }).add("delivery", {
5845
+ question: "How would you like to add the Svelte tools?",
5846
+ type: "select",
5847
+ default: "plugin",
5848
+ options: [{
5849
+ value: "plugin",
5850
+ label: "Svelte plugin",
5851
+ hint: "recommended, auto-installs & updates"
5852
+ }, {
5853
+ value: "tools",
5854
+ label: "Individual tools",
5855
+ hint: "choose exactly what to add"
5856
+ }],
5857
+ condition: ({ ide }) => ide.some((i) => CLIENTS[i]?.pluginSettings)
5858
+ }).add("tools", {
5859
+ question: "Which tools would you like to add?",
5860
+ type: "multiselect",
5861
+ default: Object.keys(TOOLS),
5862
+ options: Object.entries(TOOLS).map(([value, t]) => ({
5863
+ value,
5864
+ label: t.label,
5865
+ hint: t.hint
5866
+ })),
5867
+ required: false,
5868
+ condition: ({ ide, delivery }) => ide.some((i) => wantsLooseTools(CLIENTS[i], delivery))
5869
+ }).add("mcpSetup", {
5870
+ question: "Which MCP setup would you like to use?",
5871
+ type: "select",
5872
+ default: "remote",
5873
+ options: [{
5874
+ value: "local",
5875
+ label: "Local",
5876
+ hint: "will use stdio"
5877
+ }, {
5878
+ value: "remote",
5879
+ label: "Remote",
5880
+ hint: "will use a remote endpoint"
5881
+ }],
5882
+ condition: ({ ide, delivery, tools }) => (tools === void 0 || tools.includes("mcp")) && ide.some((i) => wantsMcpConfig(CLIENTS[i], delivery))
5883
+ }).build(),
5884
+ run: ({ sv, options }) => {
5885
+ const usePlugin = options.delivery === "plugin";
5886
+ const selected = options.tools ?? Object.keys(TOOLS);
5887
+ const selectedSkills = selected.filter((t) => TOOLS[t]?.kind === "skill");
5888
+ const selectedAgents = selected.filter((t) => TOOLS[t]?.kind === "agent");
5889
+ const wantsMcp = selected.includes("mcp");
5890
+ const getLocalConfig = (o) => {
5891
+ return {
5892
+ ...o?.typeLocal ? { type: o.typeLocal } : {},
5893
+ command: o?.command ?? "npx",
5894
+ ...o?.env ? { env: {} } : {},
5895
+ ...o?.args === null ? {} : { args: o?.args ?? ["-y", "@sveltejs/mcp"] }
5896
+ };
5897
+ };
5898
+ const getRemoteConfig = (o) => {
5899
+ return {
5900
+ ...o?.typeRemote ? { type: o.typeRemote } : {},
5901
+ url: "https://mcp.svelte.dev/mcp"
5902
+ };
5903
+ };
5904
+ const filesAdded = [];
5905
+ const filesExistingAlready = [];
5906
+ const sharedFiles = getSharedFiles();
5907
+ const mcpFiles = sharedFiles.filter((file) => file.include.includes("mcp"));
5908
+ const skillFiles = sharedFiles.filter((file) => file.include.includes("skills"));
5909
+ const agentFiles = sharedFiles.filter((file) => file.include.includes("agents"));
5910
+ const agentFile = mcpFiles.find((file) => file.name === "AGENTS.md");
5911
+ const addFile = (path, contents) => {
5912
+ sv.file(path, (content) => {
5913
+ if (content) {
5914
+ filesExistingAlready.push(path);
5915
+ return false;
5916
+ }
5917
+ if (!filesAdded.includes(path)) filesAdded.push(path);
5918
+ return contents;
5919
+ });
5920
+ };
5921
+ for (const ide of options.ide) {
5922
+ const client = CLIENTS[ide];
5923
+ if (!client) continue;
5924
+ if (client.pluginSettings && usePlugin) {
5925
+ const plugin = client.pluginSettings;
5926
+ sv.file(plugin.path, transforms.json(({ data }) => {
5927
+ data.extraKnownMarketplaces ??= {};
5928
+ data.extraKnownMarketplaces[plugin.marketplace] ??= { source: {
5929
+ source: "github",
5930
+ repo: plugin.repo
5931
+ } };
5932
+ data.enabledPlugins ??= {};
5933
+ data.enabledPlugins[plugin.id] = true;
5934
+ }));
5935
+ continue;
5936
+ }
5937
+ if (!client.agentPath) continue;
5938
+ const { mcpOptions, agentPath, agentLink, configPath, skillsPath, agentsPath, agentExtension, schema, customData, extraFiles } = client;
5939
+ if (!filesAdded.includes(agentPath)) sv.file(agentPath, (content) => {
5940
+ if (content) {
5941
+ filesExistingAlready.push(agentPath);
5942
+ return false;
5943
+ }
5944
+ filesAdded.push(agentPath);
5945
+ return agentFile?.contents ?? "";
5946
+ });
5947
+ if (agentLink) addFile(agentLink.path, agentLink.contents);
5948
+ const writeMcp = Boolean(mcpOptions) && wantsMcp;
5949
+ if (configPath && (writeMcp || customData)) sv.file(configPath, transforms.json(({ data }) => {
5950
+ if (schema) data["$schema"] = schema;
5951
+ if (customData) for (const [key, value] of Object.entries(customData)) data[key] = value;
5952
+ if (writeMcp) {
5953
+ const key = mcpOptions.serversKey ?? "mcpServers";
5954
+ data[key] ??= {};
5955
+ data[key].svelte = options.mcpSetup === "local" ? getLocalConfig(mcpOptions) : getRemoteConfig(mcpOptions);
5956
+ }
5957
+ }));
5958
+ if (extraFiles) for (const extra of extraFiles) sv.file(extra.path, transforms.json(({ data }) => {
5959
+ for (const [key, value] of Object.entries(extra.data)) data[key] = value;
5960
+ }));
5961
+ if (skillsPath) for (const file of skillFiles) {
5962
+ if (!selectedSkills.includes(file.name.split("/")[0])) continue;
5963
+ addFile(`${skillsPath}/${file.name}`, file.contents);
5964
+ }
5965
+ if (agentsPath) for (const file of agentFiles) {
5966
+ if (!selectedAgents.includes(file.name.replace(REGEX_MD, ""))) continue;
5967
+ const ext = agentExtension ?? ".md";
5968
+ addFile(`${agentsPath}/${file.name.replace(REGEX_MD, ext)}`, file.contents);
5969
+ }
5970
+ }
5971
+ if (filesExistingAlready.length > 0) R$1.warn(`${filesExistingAlready.map((path) => color.path(path)).join(", ")} already exists, we didn't touch ${filesExistingAlready.length > 1 ? "them" : "it"}. See ${color.website("https://svelte.dev/docs/ai")} for manual setup.`);
5972
+ },
5973
+ nextSteps({ options, cwd }) {
5974
+ const steps = [];
5975
+ for (const ide of options.ide) {
5976
+ const client = CLIENTS[ide];
5977
+ if (!client?.pluginSettings) continue;
5978
+ const plugin = client.pluginSettings;
5979
+ const settingsPath = path.resolve(cwd, plugin.path);
5980
+ if (!fs.existsSync(settingsPath)) continue;
5981
+ let pluginEnabled = false;
5982
+ try {
5983
+ pluginEnabled = Boolean(JSON.parse(fs.readFileSync(settingsPath, "utf8")).enabledPlugins?.[plugin.id]);
5984
+ } catch {}
5985
+ if (!pluginEnabled) continue;
5986
+ const looseDirs = [client.skillsPath, client.agentsPath].filter((dir) => Boolean(dir) && fs.existsSync(path.resolve(cwd, dir)) && fs.readdirSync(path.resolve(cwd, dir)).some((entry) => Object.keys(TOOLS).includes(entry.replace(REGEX_MD, ""))));
5987
+ if (looseDirs.length === 0) continue;
5988
+ steps.push(`${client.label}: the Svelte plugin is enabled and ${looseDirs.map((d) => color.path(d)).join(" + ")} also exist${looseDirs.length > 1 ? "" : "s"} - remove ${looseDirs.length > 1 ? "them" : "it"} (or disable the plugin) to avoid duplicate skills/sub-agents.`);
5989
+ }
5990
+ if (options.delivery === "plugin" && options.ide.includes("claude-code")) steps.push(`Open the project in Claude Code and trust the workspace - the Svelte plugin installs automatically.`);
5991
+ if (options.ide.includes("other")) steps.push(`For other clients: ${color.website(`https://svelte.dev/docs/ai/${options.mcpSetup ?? "remote"}-setup#Other-clients`)}`);
5992
+ return steps;
5993
+ }
5994
+ });
5995
+ //#endregion
5693
5996
  //#region src/addons/common.ts
5694
5997
  const ESLINT_VERSION = "^10.4.1";
5695
5998
  const addEslintConfigPrettier = transforms.script(({ ast, js }) => {
@@ -5842,6 +6145,7 @@ var better_auth_default = defineAddon({
5842
6145
  runsAfter("experimental");
5843
6146
  },
5844
6147
  run: ({ sv, cwd, language, options, directory, dependencyVersion, file }) => {
6148
+ const lib = resolveLibPrefix(dependencyVersion("@sveltejs/kit"));
5845
6149
  const svelteVersion = dependencyVersion("svelte");
5846
6150
  const svelte5 = !!svelteVersion && coerceVersion(svelteVersion).major === 5;
5847
6151
  const [ts, s5] = createPrinter(language === "ts", svelte5);
@@ -5888,7 +6192,7 @@ var better_auth_default = defineAddon({
5888
6192
  }
5889
6193
  sv.file(`${directory.lib}/server/auth.${language}`, transforms.script(({ ast, comments, js }) => {
5890
6194
  js.imports.addNamed(ast, {
5891
- from: "$lib/server/db",
6195
+ from: `${lib}/server/db`,
5892
6196
  imports: [d1 ? "getDb" : "db"]
5893
6197
  });
5894
6198
  js.imports.addNamed(ast, {
@@ -5945,7 +6249,7 @@ var better_auth_default = defineAddon({
5945
6249
  /**
5946
6250
  * DO NOT USE!
5947
6251
  *
5948
- * This instance is used by the \`better-auth\` CLI for schema generation ONLY.
6252
+ * This instance is used by the \`auth\` CLI for schema generation ONLY.
5949
6253
  * To access \`auth\` at runtime, use \`event.locals.auth\`.
5950
6254
  */
5951
6255
  export const auth = createAuth(null${ts("!")});`;
@@ -5969,7 +6273,7 @@ var better_auth_default = defineAddon({
5969
6273
  const authConfigPath = `${directory.lib}/server/auth.${language}`;
5970
6274
  const authSchemaPath = `${directory.lib}/server/db/auth.schema.${language}`;
5971
6275
  sv.file(file.package, transforms.json(({ data, json }) => {
5972
- json.packageScriptsUpsert(data, "auth:schema", `better-auth generate --config ${authConfigPath} --output ${authSchemaPath} --yes`);
6276
+ json.packageScriptsUpsert(data, "auth:schema", `auth generate --config ${authConfigPath} --output ${authSchemaPath} --yes`);
5973
6277
  }));
5974
6278
  sv.file(`${directory.lib}/server/db/auth.schema.${language}`, transforms.text(({ content }) => {
5975
6279
  if (content) return false;
@@ -5984,7 +6288,7 @@ var better_auth_default = defineAddon({
5984
6288
  sv.file("src/app.d.ts", transforms.script(({ ast, comments, js }) => {
5985
6289
  if (d1) js.imports.addNamed(ast, {
5986
6290
  imports: ["createAuth"],
5987
- from: "$lib/server/auth"
6291
+ from: `${lib}/server/auth`
5988
6292
  });
5989
6293
  js.imports.addNamed(ast, {
5990
6294
  imports: ["User", "Session"],
@@ -6008,7 +6312,7 @@ var better_auth_default = defineAddon({
6008
6312
  });
6009
6313
  js.imports.addNamed(ast, {
6010
6314
  imports: [d1 ? "createAuth" : "auth"],
6011
- from: "$lib/server/auth"
6315
+ from: `${lib}/server/auth`
6012
6316
  });
6013
6317
  env.importEnv(ast, js, ["building"]);
6014
6318
  const handleContent = dedent`
@@ -6116,7 +6420,7 @@ var better_auth_default = defineAddon({
6116
6420
  import { fail, redirect } from '@sveltejs/kit';
6117
6421
  ${ts("import type { Actions } from './$types';")}
6118
6422
  ${ts("import type { PageServerLoad } from './$types';")}
6119
- ${!d1 ? "import { auth } from '$lib/server/auth';" : ""}
6423
+ ${!d1 ? `import { auth } from '${lib}/server/auth';` : ""}
6120
6424
  ${needsAPIError ? "import { APIError } from 'better-auth/api';" : ""}
6121
6425
 
6122
6426
  export const load${ts(": PageServerLoad")} = (event) => {
@@ -6185,7 +6489,7 @@ var better_auth_default = defineAddon({
6185
6489
  import { redirect } from '@sveltejs/kit';
6186
6490
  ${ts("import type { Actions } from './$types';")}
6187
6491
  ${ts("import type { PageServerLoad } from './$types';")}
6188
- ${!d1 ? "import { auth } from '$lib/server/auth';" : ""}
6492
+ ${!d1 ? `import { auth } from '${lib}/server/auth';` : ""}
6189
6493
 
6190
6494
  export const load${ts(": PageServerLoad")} = (event) => {
6191
6495
  if (!event.locals.user) {
@@ -6352,7 +6656,7 @@ var drizzle_default = defineAddon({
6352
6656
  runsAfter("experimental");
6353
6657
  if (!isKit) return unsupported("Requires SvelteKit");
6354
6658
  },
6355
- run: ({ sv, language, options, directory, dependencyVersion, cwd, cancel, file, packageManager }) => {
6659
+ run: ({ sv, language, options, directory, dependencyVersion, cwd, cancel, file }) => {
6356
6660
  const [ts] = createPrinter(language === "ts");
6357
6661
  const baseDBPath = path.resolve(cwd, directory.lib, "server", "db");
6358
6662
  const paths = {
@@ -6369,9 +6673,8 @@ var drizzle_default = defineAddon({
6369
6673
  if (options.postgresql === "neon") sv.devDependency("@neondatabase/serverless", "^1.1.0");
6370
6674
  if (options.postgresql === "postgres.js") sv.devDependency("postgres", "^3.4.9");
6371
6675
  if (options.sqlite === "better-sqlite3") {
6372
- sv.dependency("better-sqlite3", "^12.10.0");
6676
+ sv.dependency("better-sqlite3", "^13.0.2");
6373
6677
  sv.devDependency("@types/better-sqlite3", "^7.6.13");
6374
- if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("better-sqlite3"));
6375
6678
  }
6376
6679
  if (options.sqlite === "libsql" || options.sqlite === "turso") sv.devDependency("@libsql/client", "^0.17.3");
6377
6680
  sv.file(".env", generateEnv(options, false));
@@ -6469,7 +6772,13 @@ var drizzle_default = defineAddon({
6469
6772
  })
6470
6773
  `) });
6471
6774
  }));
6472
- svelteConfig.edit({
6775
+ if (isKit3(dependencyVersion("@sveltejs/kit"))) {
6776
+ const configFile = language === "ts" ? "tsconfig.json" : "jsconfig.json";
6777
+ if (fileExists(cwd, configFile)) sv.file(configFile, transforms.json(({ data }) => {
6778
+ const include = data.include ??= ["src"];
6779
+ if (!include.includes(`drizzle.config.${language}`)) include.push(`drizzle.config.${language}`);
6780
+ }));
6781
+ } else svelteConfig.edit({
6473
6782
  sv,
6474
6783
  cwd
6475
6784
  }, ({ override, js }) => {
@@ -6885,12 +7194,25 @@ const FEATURES = {
6885
7194
  hint: "kit ^2 only",
6886
7195
  inNext: false
6887
7196
  },
6888
- handleRenderingErrors: { label: "rendering error boundaries" },
7197
+ handleRenderingErrors: {
7198
+ label: "rendering error boundaries",
7199
+ hint: "kit ^2 only",
7200
+ inNext: false
7201
+ },
6889
7202
  forkPreloads: {
6890
7203
  label: "forked preloading",
6891
7204
  off: true
6892
7205
  }
6893
7206
  };
7207
+ const SOURCE_EXTENSIONS = [
7208
+ ".svelte",
7209
+ ".svelte.ts",
7210
+ ".svelte.js",
7211
+ ".ts",
7212
+ ".js",
7213
+ ".svx",
7214
+ ".md"
7215
+ ];
6894
7216
  const KIT3_PEERS = {
6895
7217
  vite: "^8.0.0",
6896
7218
  "@sveltejs/vite-plugin-svelte": "^7.0.0",
@@ -6922,7 +7244,7 @@ var experimental_default = defineAddon({
6922
7244
  required: false
6923
7245
  }).build(),
6924
7246
  setup: ({ runsAfter }) => runsAfter("sveltekitAdapter"),
6925
- run: ({ sv, cwd, options, language, dependencyVersion }) => {
7247
+ run: ({ sv, cwd, options, language, directory, dependencyVersion }) => {
6926
7248
  const kitNext = options.versions.includes("kit");
6927
7249
  if (kitNext) {
6928
7250
  sv.devDependency("@sveltejs/kit", "next");
@@ -6938,6 +7260,23 @@ var experimental_default = defineAddon({
6938
7260
  };
6939
7261
  for (const name of Object.keys(deps)) if (name.startsWith("@sveltejs/adapter-")) sv.devDependency(name, "next");
6940
7262
  }
7263
+ if (kitNext) {
7264
+ for (const name of ["tsconfig.json", "jsconfig.json"]) {
7265
+ if (!fileExists(cwd, name)) continue;
7266
+ sv.file(name, transforms.json(({ data }) => {
7267
+ data.extends = KIT3_TSCONFIG;
7268
+ data.include ??= [directory.src];
7269
+ for (const [key, value] of Object.entries(data.compilerOptions ?? {})) if (KIT3_TSCONFIG_DEFAULT[key] === value) delete data.compilerOptions[key];
7270
+ }));
7271
+ }
7272
+ sv.file("package.json", transforms.json(({ data }) => {
7273
+ data.imports = {
7274
+ ...libSubpathImports(directory.lib),
7275
+ ...data.imports
7276
+ };
7277
+ }));
7278
+ for (const relative of sourceFiles(cwd, directory.src)) sv.file(relative, (content) => content.includes("$lib") ? content.replaceAll("$lib", "#lib") : false);
7279
+ }
6941
7280
  const config = {};
6942
7281
  for (const [name, f] of Object.entries(FEATURES)) {
6943
7282
  if (!options.features.includes(name)) continue;
@@ -6953,147 +7292,12 @@ var experimental_default = defineAddon({
6953
7292
  }, ({ override }) => override(config));
6954
7293
  }
6955
7294
  });
6956
- var mcp_default = defineAddon({
6957
- id: "mcp",
6958
- shortDescription: "Svelte MCP",
6959
- homepage: "https://svelte.dev/docs/mcp",
6960
- options: defineAddonOptions().add("ide", {
6961
- question: "Which client would you like to use?",
6962
- type: "multiselect",
6963
- default: [],
6964
- options: [
6965
- {
6966
- value: "claude-code",
6967
- label: "claude code"
6968
- },
6969
- {
6970
- value: "cursor",
6971
- label: "Cursor"
6972
- },
6973
- {
6974
- value: "gemini",
6975
- label: "Gemini"
6976
- },
6977
- {
6978
- value: "opencode",
6979
- label: "opencode"
6980
- },
6981
- {
6982
- value: "vscode",
6983
- label: "VSCode"
6984
- },
6985
- {
6986
- value: "other",
6987
- label: "Other"
6988
- }
6989
- ],
6990
- required: true
6991
- }).add("setup", {
6992
- question: "What setup would you like to use?",
6993
- type: "select",
6994
- default: "remote",
6995
- options: [{
6996
- value: "local",
6997
- label: "Local",
6998
- hint: "will use stdio"
6999
- }, {
7000
- value: "remote",
7001
- label: "Remote",
7002
- hint: "will use a remote endpoint"
7003
- }],
7004
- required: true,
7005
- condition: ({ ide }) => !(ide.length === 1 && ide.includes("opencode"))
7006
- }).build(),
7007
- run: ({ sv, options }) => {
7008
- const getLocalConfig = (o) => {
7009
- return {
7010
- ...o?.typeLocal ? { type: o.typeLocal } : {},
7011
- command: o?.command ?? "npx",
7012
- ...o?.env ? { env: {} } : {},
7013
- ...o?.args === null ? {} : { args: o?.args ?? ["-y", "@sveltejs/mcp"] }
7014
- };
7015
- };
7016
- const getRemoteConfig = (o) => {
7017
- return {
7018
- ...o?.typeRemote ? { type: o.typeRemote } : {},
7019
- url: "https://mcp.svelte.dev/mcp"
7020
- };
7021
- };
7022
- const configurator = {
7023
- "claude-code": {
7024
- agentPath: "CLAUDE.md",
7025
- configPath: ".mcp.json",
7026
- mcpOptions: {
7027
- typeLocal: "stdio",
7028
- typeRemote: "http",
7029
- env: true
7030
- }
7031
- },
7032
- cursor: {
7033
- agentPath: "AGENTS.md",
7034
- configPath: ".cursor/mcp.json",
7035
- mcpOptions: {}
7036
- },
7037
- gemini: {
7038
- agentPath: "GEMINI.md",
7039
- configPath: ".gemini/settings.json",
7040
- schema: "https://raw.githubusercontent.com/google-gemini/gemini-cli/main/schemas/settings.schema.json",
7041
- mcpOptions: {}
7042
- },
7043
- opencode: {
7044
- agentPath: "AGENTS.md",
7045
- configPath: ".opencode/opencode.json",
7046
- schema: "https://opencode.ai/config.json",
7047
- customData: { plugin: ["@sveltejs/opencode"] },
7048
- extraFiles: [{
7049
- path: ".opencode/svelte.json",
7050
- data: { $schema: "https://svelte.dev/opencode/schema.json" }
7051
- }]
7052
- },
7053
- vscode: {
7054
- agentPath: "AGENTS.md",
7055
- configPath: ".vscode/mcp.json",
7056
- mcpOptions: { serversKey: "servers" }
7057
- },
7058
- other: { other: true }
7059
- };
7060
- const filesAdded = [];
7061
- const filesExistingAlready = [];
7062
- const agentFile = getSharedFiles().filter((file) => file.include.includes("mcp")).find((file) => file.name === "AGENTS.md");
7063
- for (const ide of options.ide) {
7064
- const value = configurator[ide];
7065
- if (value === void 0) continue;
7066
- if ("other" in value) continue;
7067
- const { mcpOptions, agentPath, configPath, schema, customData, extraFiles } = value;
7068
- if (!filesAdded.includes(agentPath)) sv.file(agentPath, (content) => {
7069
- if (content) {
7070
- filesExistingAlready.push(agentPath);
7071
- return false;
7072
- }
7073
- filesAdded.push(agentPath);
7074
- return agentFile?.contents ?? "";
7075
- });
7076
- sv.file(configPath, transforms.json(({ data }) => {
7077
- if (schema) data["$schema"] = schema;
7078
- if (customData) for (const [key, value] of Object.entries(customData)) data[key] = value;
7079
- if (mcpOptions) {
7080
- const key = mcpOptions.serversKey ?? "mcpServers";
7081
- data[key] ??= {};
7082
- data[key].svelte = options.setup === "local" ? getLocalConfig(mcpOptions) : getRemoteConfig(mcpOptions);
7083
- }
7084
- }));
7085
- if (extraFiles) for (const extra of extraFiles) sv.file(extra.path, transforms.json(({ data }) => {
7086
- for (const [key, value] of Object.entries(extra.data)) data[key] = value;
7087
- }));
7088
- }
7089
- if (filesExistingAlready.length > 0) R$1.warn(`${filesExistingAlready.map((path) => color.path(path)).join(", ")} already exists, we didn't touch ${filesExistingAlready.length > 1 ? "them" : "it"}. See ${color.website("https://svelte.dev/docs/mcp/overview#Usage")} for manual setup.`);
7090
- },
7091
- nextSteps({ options }) {
7092
- const steps = [];
7093
- if (options.ide.includes("other")) steps.push(`For other clients: ${color.website(`https://svelte.dev/docs/mcp/${options.setup}-setup#Other-clients`)}`);
7094
- return steps;
7095
- }
7096
- });
7295
+ /** Workspace-relative source files under `src`, for the `$lib` -> `#lib` rewrite. */
7296
+ function sourceFiles(cwd, src) {
7297
+ const root = path.resolve(cwd, src);
7298
+ if (!fs.existsSync(root)) return [];
7299
+ return fs.readdirSync(root, { recursive: true }).map((entry) => path.join(src, entry)).filter((relative) => SOURCE_EXTENSIONS.some((ext) => relative.endsWith(ext)) && fs.statSync(path.resolve(cwd, relative)).isFile());
7300
+ }
7097
7301
  //#endregion
7098
7302
  //#region src/addons/mdsvex.ts
7099
7303
  var mdsvex_default = defineAddon({
@@ -7162,11 +7366,15 @@ var paraglide_default = defineAddon({
7162
7366
  shortDescription: "i18n",
7163
7367
  homepage: "https://inlang.com/m/gerre34r/library-inlang-paraglideJs",
7164
7368
  options: options$3,
7165
- setup: ({ isKit, unsupported }) => {
7369
+ setup: ({ isKit, unsupported, runsAfter }) => {
7166
7370
  if (!isKit) unsupported("Requires SvelteKit");
7371
+ runsAfter("experimental");
7167
7372
  },
7168
- run: ({ sv, options, file, language, directory }) => {
7373
+ run: ({ sv, options, file, language, directory, dependencyVersion }) => {
7169
7374
  const [ts] = createPrinter(language === "ts");
7375
+ const kitRange = dependencyVersion("@sveltejs/kit");
7376
+ const lib = resolveLibPrefix(kitRange);
7377
+ const pathType = isKit3(kitRange) ? "Path" : "Pathname";
7170
7378
  const paraglideOutDir = `${directory.lib}/paraglide`;
7171
7379
  sv.devDependency("@inlang/paraglide-js", "^2.18.2");
7172
7380
  sv.file(file.viteConfig, transforms.script(({ ast, js }) => {
@@ -7183,7 +7391,7 @@ var paraglide_default = defineAddon({
7183
7391
  }));
7184
7392
  sv.file(`src/hooks.${language}`, transforms.script(({ ast, comments, js }) => {
7185
7393
  js.imports.addNamed(ast, {
7186
- from: "$lib/paraglide/runtime",
7394
+ from: `${lib}/paraglide/runtime`,
7187
7395
  imports: ["deLocalizeUrl"]
7188
7396
  });
7189
7397
  const expression = js.common.parseExpression("(request) => deLocalizeUrl(request.url).pathname");
@@ -7206,11 +7414,11 @@ var paraglide_default = defineAddon({
7206
7414
  }));
7207
7415
  sv.file(`src/hooks.server.${language}`, transforms.script(({ ast, comments, js }) => {
7208
7416
  js.imports.addNamed(ast, {
7209
- from: "$lib/paraglide/server",
7417
+ from: `${lib}/paraglide/server`,
7210
7418
  imports: ["paraglideMiddleware"]
7211
7419
  });
7212
7420
  js.imports.addNamed(ast, {
7213
- from: "$lib/paraglide/runtime",
7421
+ from: `${lib}/paraglide/runtime`,
7214
7422
  imports: ["getTextDirection"]
7215
7423
  });
7216
7424
  js.kit.addHooksHandle(ast, {
@@ -7250,7 +7458,7 @@ var paraglide_default = defineAddon({
7250
7458
  sv.file(`${directory.kitRoutes}/+layout.svelte`, transforms.svelteScript({ language }, ({ ast, svelte, js }) => {
7251
7459
  js.imports.addNamed(ast.instance.content, {
7252
7460
  imports: ["locales", "localizeHref"],
7253
- from: "$lib/paraglide/runtime"
7461
+ from: `${lib}/paraglide/runtime`
7254
7462
  });
7255
7463
  js.imports.addNamed(ast.instance.content, {
7256
7464
  imports: ["page"],
@@ -7261,14 +7469,14 @@ var paraglide_default = defineAddon({
7261
7469
  from: "$app/paths"
7262
7470
  });
7263
7471
  if (language === "ts") js.imports.addNamed(ast.instance.content, {
7264
- imports: ["Pathname"],
7472
+ imports: [pathType],
7265
7473
  from: "$app/types",
7266
7474
  isType: true
7267
7475
  });
7268
7476
  svelte.addFragment(ast, dedent`
7269
7477
  <div style="display:none">
7270
7478
  {#each locales as locale (locale)}
7271
- <a href={resolve(localizeHref(page.url.pathname, { locale })${ts(" as Pathname")})}>{locale}</a>
7479
+ <a href={resolve(localizeHref(page.url.pathname, { locale })${ts(` as ${pathType}`)})}>{locale}</a>
7272
7480
  {/each}
7273
7481
  </div>`, { language });
7274
7482
  }));
@@ -7277,11 +7485,11 @@ var paraglide_default = defineAddon({
7277
7485
  sv.file(`${directory.kitRoutes}/demo/paraglide/+page.svelte`, transforms.svelteScript({ language }, ({ ast, svelte, js }) => {
7278
7486
  js.imports.addNamed(ast.instance.content, {
7279
7487
  imports: { m: "m" },
7280
- from: "$lib/paraglide/messages.js"
7488
+ from: `${lib}/paraglide/messages.js`
7281
7489
  });
7282
7490
  js.imports.addNamed(ast.instance.content, {
7283
7491
  imports: { setLocale: "setLocale" },
7284
- from: "$lib/paraglide/runtime"
7492
+ from: `${lib}/paraglide/runtime`
7285
7493
  });
7286
7494
  let templateCode = "<h1>{m.hello_world({ name: 'SvelteKit User' })}</h1>";
7287
7495
  const { validLanguageTags } = parseLanguageTagInput(options.languageTags);
@@ -7559,7 +7767,7 @@ var sveltekit_adapter_default = defineAddon({
7559
7767
  });
7560
7768
  if (adapter.package === "@sveltejs/adapter-cloudflare") {
7561
7769
  sv.devDependency("wrangler", "^4.97.0");
7562
- if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("workerd", "sharp"));
7770
+ if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("workerd"));
7563
7771
  const ext = fileExists(cwd, "wrangler.toml") ? "toml" : "jsonc";
7564
7772
  const applyWranglerConfig = (data) => {
7565
7773
  if (ext === "jsonc") data.$schema ??= "./node_modules/wrangler/config-schema.json";
@@ -7635,11 +7843,10 @@ var tailwindcss_default = defineAddon({
7635
7843
  default: [],
7636
7844
  required: false
7637
7845
  }).build(),
7638
- run: ({ sv, options, file, isKit, directory, dependencyVersion, language, packageManager }) => {
7846
+ run: ({ sv, options, file, isKit, directory, dependencyVersion, language }) => {
7639
7847
  const prettierInstalled = Boolean(dependencyVersion("prettier"));
7640
7848
  sv.devDependency("tailwindcss", "^4.3.0");
7641
7849
  sv.devDependency("@tailwindcss/vite", "^4.3.0");
7642
- if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("@tailwindcss/oxide"));
7643
7850
  if (prettierInstalled) sv.devDependency("prettier-plugin-tailwindcss", "^0.8.0");
7644
7851
  for (const plugin of plugins) {
7645
7852
  if (!options.plugins.includes(plugin.id)) continue;
@@ -7877,7 +8084,7 @@ const officialAddons$1 = {
7877
8084
  mdsvex: mdsvex_default,
7878
8085
  paraglide: paraglide_default,
7879
8086
  storybook: storybook_default,
7880
- mcp: mcp_default,
8087
+ aiTools: ai_tools_default,
7881
8088
  experimental: experimental_default
7882
8089
  };
7883
8090
  function getAddonDetails(id) {
@@ -10693,50 +10900,61 @@ async function formatFiles(options) {
10693
10900
  const { start, stop } = vt();
10694
10901
  start("Formatting modified files");
10695
10902
  const args = [
10696
- "prettier",
10697
10903
  "--write",
10698
10904
  "--ignore-unknown",
10699
10905
  ...options.filesToFormat
10700
10906
  ];
10701
- const cmd = resolveCommand(options.packageManager, "execute-local", args);
10907
+ let result = await run("prettier", args, options.cwd);
10908
+ if (result.notFound) {
10909
+ const cmd = resolveCommand(options.packageManager, "execute-local", ["prettier", ...args]);
10910
+ result = await run(cmd.command, cmd.args, options.cwd);
10911
+ }
10912
+ if (result.error !== void 0) {
10913
+ stop("Failed to format files");
10914
+ R$1.error(result.error);
10915
+ return;
10916
+ }
10917
+ stop("Successfully formatted modified files");
10918
+ }
10919
+ async function run(command, args, cwd) {
10702
10920
  try {
10703
- const result = await z(cmd.command, cmd.args, {
10921
+ await z(command, args, {
10704
10922
  nodeOptions: {
10705
- cwd: options.cwd,
10923
+ cwd,
10706
10924
  stdio: "pipe"
10707
10925
  },
10708
10926
  throwOnError: true
10709
10927
  });
10710
- if (result.exitCode !== 0) {
10711
- stop("Failed to format files");
10712
- R$1.error(result.stderr);
10713
- return;
10714
- }
10928
+ return {};
10715
10929
  } catch (e) {
10716
- stop("Failed to format files");
10717
- R$1.error(e?.output?.stderr || "unknown error");
10718
- return;
10930
+ if (e?.code === "ENOENT") return {
10931
+ notFound: true,
10932
+ error: `${command} not found`
10933
+ };
10934
+ const output = e?.output;
10935
+ return { error: [output?.stderr, output?.stdout].filter(Boolean).join("\n").trim() || (e instanceof Error ? e.message : "unknown error") };
10719
10936
  }
10720
- stop("Successfully formatted modified files");
10721
10937
  }
10722
10938
  //#endregion
10723
10939
  //#region src/core/package-manager.ts
10724
10940
  const AGENT_NAMES = AGENTS.filter((agent) => !agent.includes("@"));
10725
- const agentOptions = AGENT_NAMES.map((pm) => ({
10726
- value: pm,
10727
- label: pm
10728
- }));
10729
- agentOptions.unshift({
10730
- label: "None",
10731
- value: void 0
10732
- });
10733
10941
  const installOption = new Option("--install <package-manager>", "installs dependencies with a specified package manager").choices(AGENT_NAMES);
10734
10942
  async function packageManagerPrompt(cwd) {
10735
10943
  const agent = (await detect({ cwd }))?.name ?? getUserAgent();
10736
10944
  if (!V.stdout.isTTY) return agent;
10737
10945
  const pm = await Ee({
10738
10946
  message: "Which package manager do you want to install dependencies with?",
10739
- options: agentOptions,
10947
+ options: [{
10948
+ label: "None",
10949
+ value: void 0
10950
+ }, ...AGENT_NAMES.map((agent) => {
10951
+ const installed = isInstalled(agent);
10952
+ return {
10953
+ value: agent,
10954
+ label: installed ? agent : color.dim(`${agent} (not installed)`),
10955
+ installed
10956
+ };
10957
+ }).sort((a, b) => Number(b.installed) - Number(a.installed))],
10740
10958
  initialValue: agent
10741
10959
  });
10742
10960
  if (R$2(pm)) {
@@ -10745,7 +10963,12 @@ async function packageManagerPrompt(cwd) {
10745
10963
  }
10746
10964
  return pm;
10747
10965
  }
10966
+ /** Returns `false` when the package manager isn't installed and the install was skipped. */
10748
10967
  async function installDependencies(agent, cwd) {
10968
+ if (!isInstalled(agent)) {
10969
+ R$1.warn(`${color.command(agent)} is not installed, skipping dependency installation.`);
10970
+ return false;
10971
+ }
10749
10972
  const task = Pe({
10750
10973
  title: `Installing dependencies with ${color.command(agent)}...`,
10751
10974
  limit: Math.ceil(V.stdout.rows / 2),
@@ -10769,12 +10992,12 @@ async function installDependencies(agent, cwd) {
10769
10992
  } catch {}
10770
10993
  if ((proc.exitCode ?? 0) === 0) {
10771
10994
  task.success(`Successfully installed dependencies with ${color.command(agent)}`);
10772
- return;
10995
+ return true;
10773
10996
  }
10774
10997
  if (agent === "pnpm" && output.join("\n").includes("ERR_PNPM_IGNORED_BUILDS")) {
10775
10998
  task.success(`Installed dependencies with ${color.command(agent)}`);
10776
10999
  R$1.warn(`Some build scripts were skipped. Run ${color.command(`${agent} approve-builds`)} to approve them.`);
10777
- return;
11000
+ return true;
10778
11001
  }
10779
11002
  task.error("Failed to install dependencies");
10780
11003
  ge("Operation failed.");
@@ -10791,6 +11014,20 @@ function getUserAgent() {
10791
11014
  const name = pmSpec.substring(0, separatorPos);
10792
11015
  return AGENTS.includes(name) ? name : void 0;
10793
11016
  }
11017
+ const installedCache = /* @__PURE__ */ new Map();
11018
+ function isInstalled(agent) {
11019
+ let installed = installedCache.get(agent);
11020
+ if (installed === void 0) {
11021
+ try {
11022
+ B(agent, ["--version"], { nodeOptions: { stdio: "ignore" } });
11023
+ installed = true;
11024
+ } catch {
11025
+ installed = false;
11026
+ }
11027
+ installedCache.set(agent, installed);
11028
+ }
11029
+ return installed;
11030
+ }
10794
11031
  function addPnpmAllowBuilds(cwd, packageManager, ...packages) {
10795
11032
  if (packageManager !== "pnpm" || packages.length === 0) return;
10796
11033
  const found = up$1("pnpm-workspace.yaml", { cwd });
@@ -11225,7 +11462,7 @@ const create = new Command("create").description("Scaffold a new project (--add
11225
11462
  V.exit(1);
11226
11463
  }
11227
11464
  runCommand(async () => {
11228
- const { directory, addOnNextSteps, packageManager } = await createProject(cwd, options);
11465
+ const { directory, addOnNextSteps, packageManager, depsInstalled } = await createProject(cwd, options);
11229
11466
  let i = 1;
11230
11467
  const initialSteps = ["📁 Project steps", ""];
11231
11468
  const relative = path.relative(V.cwd(), directory);
@@ -11234,7 +11471,8 @@ const create = new Command("create").description("Scaffold a new project (--add
11234
11471
  const pathHasSpaces = relative.includes(" ");
11235
11472
  initialSteps.push(` ${i++}: ${color.command(`cd ${pathHasSpaces ? `"${relative}"` : relative}`)}`);
11236
11473
  }
11237
- if (!packageManager) initialSteps.push(` ${i++}: ${color.command(resolveCommandArray(pm, "install", []))}`);
11474
+ if (packageManager && !depsInstalled) initialSteps.push(` ${i++}: Install ${color.command(pm)}`);
11475
+ if (!packageManager || !depsInstalled) initialSteps.push(` ${i++}: ${color.command(resolveCommandArray(pm, "install", []))}`);
11238
11476
  const steps = [
11239
11477
  ...initialSteps,
11240
11478
  ` ${i++}: ${color.command(resolveCommandArray(pm, "run", ["dev", "--open"]))}`,
@@ -11410,18 +11648,20 @@ async function createProject(cwd, options) {
11410
11648
  updateAgent(directory, language, packageManager ?? "npm", loadedAddons);
11411
11649
  const addOnNextSteps = getNextSteps(addOnSuccessfulAddons, workspace, answers, addonSetupResults);
11412
11650
  addPnpmAllowBuilds(projectPath, packageManager, "esbuild");
11651
+ let depsInstalled = false;
11413
11652
  if (packageManager) {
11414
- await installDependencies(packageManager, projectPath);
11415
- await formatFiles({
11653
+ depsInstalled = await installDependencies(packageManager, projectPath);
11654
+ if (depsInstalled) await formatFiles({
11416
11655
  packageManager,
11417
11656
  cwd: projectPath,
11418
- filesToFormat: addOnFilesToFormat
11657
+ filesToFormat: addOnSuccessfulAddons.some((addon) => addon.addon.id === "prettier") ? ["."] : addOnFilesToFormat
11419
11658
  });
11420
11659
  }
11421
11660
  return {
11422
11661
  directory: projectPath,
11423
11662
  addOnNextSteps,
11424
- packageManager
11663
+ packageManager,
11664
+ depsInstalled
11425
11665
  };
11426
11666
  }
11427
11667
  async function createProjectFromPlayground(url, cwd) {
@@ -11713,9 +11953,9 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
11713
11953
  }
11714
11954
  for (const loaded of addons) answers[loaded.addon.id] ??= {};
11715
11955
  let setupResults = {};
11716
- if (addons.length > 0) setupResults = setupAddons(addons, workspace);
11956
+ if (addons.length > 0) setupResults = await setupAddons(addons, workspace);
11717
11957
  if (addons.length === 0) {
11718
- const results = setupAddons(officialAddons.map((a) => createLoadedAddon(a)), workspace);
11958
+ const results = await setupAddons(officialAddons.map((a) => createLoadedAddon(a)), workspace);
11719
11959
  const addonOptions = officialAddons.filter(({ id, hidden }) => results[id].unsupported.length === 0 && !hidden).map(({ id, homepage, shortDescription }) => ({
11720
11960
  label: id,
11721
11961
  value: id,
@@ -11735,11 +11975,11 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
11735
11975
  addons.push(createLoadedAddon(addon));
11736
11976
  answers[id] = {};
11737
11977
  }
11738
- setupResults = setupAddons(addons, workspace);
11978
+ setupResults = await setupAddons(addons, workspace);
11739
11979
  }
11740
11980
  const missingSetupResults = addons.filter((a) => !setupResults[a.addon.id]);
11741
11981
  if (missingSetupResults.length > 0) {
11742
- const additionalSetupResults = setupAddons(missingSetupResults, workspace);
11982
+ const additionalSetupResults = await setupAddons(missingSetupResults, workspace);
11743
11983
  Object.assign(setupResults, additionalSetupResults);
11744
11984
  }
11745
11985
  const dependencyChains = /* @__PURE__ */ new Map();
@@ -11779,7 +12019,7 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
11779
12019
  }
11780
12020
  const newlyAddedAddons = addons.filter((a) => !setupResults[a.addon.id]);
11781
12021
  if (newlyAddedAddons.length > 0) {
11782
- const newSetupResults = setupAddons(newlyAddedAddons, workspace);
12022
+ const newSetupResults = await setupAddons(newlyAddedAddons, workspace);
11783
12023
  Object.assign(setupResults, newSetupResults);
11784
12024
  }
11785
12025
  }
@@ -11851,7 +12091,7 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
11851
12091
  };
11852
12092
  }
11853
12093
  async function runAddonsApply({ answers, options, loadedAddons, setupResults, workspace, fromCommand }) {
11854
- if (!setupResults) setupResults = setupAddons(loadedAddons.length ? loadedAddons : officialAddons.map((a) => createLoadedAddon(a)), workspace);
12094
+ if (!setupResults) setupResults = await setupAddons(loadedAddons.length ? loadedAddons : officialAddons.map((a) => createLoadedAddon(a)), workspace);
11855
12095
  if (loadedAddons.length === 0) return {
11856
12096
  nextSteps: [],
11857
12097
  argsFormattedAddons: [],
@@ -11910,17 +12150,20 @@ async function runAddonsApply({ answers, options, loadedAddons, setupResults, wo
11910
12150
  if (!options.gitCheck) argsFormattedAddons.push("--no-git-check");
11911
12151
  buildAndLogArgs(packageManager, "add", argsFormattedAddons);
11912
12152
  }
12153
+ let depsInstalled = true;
11913
12154
  if (packageManager) {
11914
12155
  workspace.packageManager = packageManager;
11915
- await installDependencies(packageManager, options.cwd);
11916
- await formatFiles({
12156
+ depsInstalled = await installDependencies(packageManager, options.cwd);
12157
+ if (depsInstalled) await formatFiles({
11917
12158
  packageManager,
11918
12159
  cwd: options.cwd,
11919
12160
  filesToFormat
11920
12161
  });
11921
12162
  }
12163
+ const nextSteps = getNextSteps(successfulAddons, workspace, answers, setupResults);
12164
+ if (packageManager && !depsInstalled) nextSteps.unshift(`Install ${color.command(packageManager)}, then run ${color.command(resolveCommandArray(packageManager, "install", []))}`);
11922
12165
  return {
11923
- nextSteps: getNextSteps(successfulAddons, workspace, answers, setupResults),
12166
+ nextSteps,
11924
12167
  argsFormattedAddons,
11925
12168
  filesToFormat,
11926
12169
  successfulAddons,
@@ -12133,7 +12376,7 @@ async function add({ addons, cwd, options, packageManager = "npm" }) {
12133
12376
  loadedAddons,
12134
12377
  workspace,
12135
12378
  options,
12136
- setupResults: setupAddons(loadedAddons, workspace)
12379
+ setupResults: await setupAddons(loadedAddons, workspace)
12137
12380
  });
12138
12381
  }
12139
12382
  async function applyAddons({ loadedAddons, workspace, setupResults, options }) {
@@ -12176,29 +12419,35 @@ async function applyAddons({ loadedAddons, workspace, setupResults, options }) {
12176
12419
  };
12177
12420
  }
12178
12421
  /** Setup addons - takes LoadedAddon[] and returns setup results */
12179
- function setupAddons(loadedAddons, workspace) {
12422
+ async function setupAddons(loadedAddons, workspace) {
12180
12423
  const setupResults = {};
12181
12424
  for (const loaded of loadedAddons) {
12182
12425
  const addon = loaded.addon;
12426
+ const additionalOptions = {};
12183
12427
  const setupResult = {
12184
12428
  unsupported: [],
12185
12429
  dependsOn: [],
12186
- runsAfter: []
12430
+ runsAfter: [],
12431
+ additionalOptions
12187
12432
  };
12188
12433
  try {
12189
- addon.setup?.({
12434
+ await addon.setup?.({
12190
12435
  ...workspace,
12191
12436
  dependsOn: (name) => {
12192
12437
  setupResult.dependsOn.push(name);
12193
12438
  setupResult.runsAfter.push(name);
12194
12439
  },
12195
12440
  unsupported: (reason) => setupResult.unsupported.push(reason),
12196
- runsAfter: (name) => setupResult.runsAfter.push(name)
12441
+ runsAfter: (name) => setupResult.runsAfter.push(name),
12442
+ addOption: (key, question) => {
12443
+ additionalOptions[key] = question;
12444
+ }
12197
12445
  });
12198
12446
  } catch (err) {
12199
12447
  const msg = err instanceof Error ? err.message : String(err);
12200
12448
  throw new Error(`Add-on '${addon.id}' failed during setup: ${msg}\n\n${getErrorHint(loaded.reference.source)}`, { cause: err });
12201
12449
  }
12450
+ if (Object.keys(additionalOptions).length > 0) Object.assign(addon.options, additionalOptions);
12202
12451
  setupResults[addon.id] = setupResult;
12203
12452
  }
12204
12453
  return setupResults;
@@ -12285,10 +12534,30 @@ async function runAddon({ addon, loaded, multiple, workspace, workspaceOptions }
12285
12534
  cancels
12286
12535
  };
12287
12536
  }
12537
+ /**
12538
+ * Orders add-ons so every `runsAfter` is honoured, keeping the original order between add-ons that
12539
+ * don't constrain each other. Cycles and unknown ids are ignored rather than fatal - an add-on that
12540
+ * can't be placed simply keeps its position.
12541
+ */
12288
12542
  function orderAddons(addons, setupResults) {
12289
- return addons.sort((a, b) => {
12290
- return setupResults[a.id]?.runsAfter?.length - setupResults[b.id]?.runsAfter?.length;
12291
- });
12543
+ const byId = new Map(addons.map((addon) => [addon.id, addon]));
12544
+ const ordered = [];
12545
+ const placed = /* @__PURE__ */ new Set();
12546
+ const visiting = /* @__PURE__ */ new Set();
12547
+ const place = (addon) => {
12548
+ if (placed.has(addon.id) || visiting.has(addon.id)) return;
12549
+ visiting.add(addon.id);
12550
+ for (const id of setupResults[addon.id]?.runsAfter ?? []) {
12551
+ const dependency = byId.get(id);
12552
+ if (dependency) place(dependency);
12553
+ }
12554
+ visiting.delete(addon.id);
12555
+ placed.add(addon.id);
12556
+ ordered.push(addon);
12557
+ };
12558
+ const seeded = [...addons].sort((a, b) => (setupResults[a.id]?.runsAfter?.length ?? 0) - (setupResults[b.id]?.runsAfter?.length ?? 0));
12559
+ for (const addon of seeded) place(addon);
12560
+ return ordered;
12292
12561
  }
12293
12562
  //#endregion
12294
12563
  export { __toESM as S, name as _, detectPackageManager as a, __commonJSMin as b, defineAddonOptions as c, Command as d, R as f, helpConfig as g, forwardExitCode as h, addPnpmAllowBuilds as i, from as l, create$1 as m, add$1 as n, officialAddons$1 as o, z as p, create as r, defineAddon as s, add as t, program as u, version as v, __require as x, svDeprecated as y };