skill-creator 2.0.0 → 2.0.1

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 (32) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cli.js +107 -27
  3. package/dist/cli.js.map +3 -3
  4. package/dist/daemon.js +106 -26
  5. package/dist/daemon.js.map +3 -3
  6. package/dist/package.json +1 -1
  7. package/dist/webui/_app/immutable/chunks/{BySEbwqx.js → B0pe_B_o.js} +1 -1
  8. package/dist/webui/_app/immutable/chunks/{B_YFzSAv.js → BQ8kO0xi.js} +1 -1
  9. package/dist/webui/_app/immutable/chunks/BZ2Jwl6O.js +1 -0
  10. package/dist/webui/_app/immutable/chunks/{D25cXQtk.js → Bg2k7op5.js} +1 -1
  11. package/dist/webui/_app/immutable/chunks/{DWcQbrnv.js → BoMQFGOq.js} +1 -1
  12. package/dist/webui/_app/immutable/chunks/{DEtYLPO4.js → CGrKeCdk.js} +1 -1
  13. package/dist/webui/_app/immutable/chunks/{IYkYSIV6.js → COoMyR0G.js} +1 -1
  14. package/dist/webui/_app/immutable/chunks/{D-ecV3TD.js → CqzSRtkf.js} +1 -1
  15. package/dist/webui/_app/immutable/chunks/{D0xHg31U.js → CsaIfA9E.js} +1 -1
  16. package/dist/webui/_app/immutable/chunks/{DJNLWtK-.js → D-Jy42mM.js} +1 -1
  17. package/dist/webui/_app/immutable/chunks/{B2zyE4XX.js → DPrjly2t.js} +1 -1
  18. package/dist/webui/_app/immutable/chunks/{BD9g8Udg.js → FuwccWbx.js} +1 -1
  19. package/dist/webui/_app/immutable/chunks/{BaH4uqzh.js → JcDjicYT.js} +1 -1
  20. package/dist/webui/_app/immutable/chunks/{BrDKAjtR.js → O2CEZ91h.js} +1 -1
  21. package/dist/webui/_app/immutable/chunks/{iicbWqXp.js → gkPAnPzC.js} +1 -1
  22. package/dist/webui/_app/immutable/chunks/{CEpOi93z.js → r1y9r7sj.js} +1 -1
  23. package/dist/webui/_app/immutable/entry/{app.CbFi8HIH.js → app.BisiObvX.js} +2 -2
  24. package/dist/webui/_app/immutable/entry/start.uEYh5tXy.js +1 -0
  25. package/dist/webui/_app/immutable/nodes/{0.C7-AKGsj.js → 0.C8yGM2gr.js} +2 -2
  26. package/dist/webui/_app/immutable/nodes/{1.raBmjc20.js → 1.BUJKZ337.js} +1 -1
  27. package/dist/webui/_app/immutable/nodes/{2.ewWz-Ki-.js → 2.Db-aM2Oa.js} +1 -1
  28. package/dist/webui/_app/version.json +1 -1
  29. package/dist/webui/index.html +14 -14
  30. package/package.json +1 -1
  31. package/dist/webui/_app/immutable/chunks/DLuJKUyD.js +0 -1
  32. package/dist/webui/_app/immutable/entry/start.C3bV1TCO.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.1 (2026-09-15)
4
+
5
+ Hotfix for the native file picker shipped in 2.0.0.
6
+
7
+ ### Fixed
8
+
9
+ - **Native file picker never opened (macOS)** — the `@xmorse/rfd` async dialog
10
+ panics off the main thread in non-GUI host processes, leaving the RPC promise
11
+ pending forever: the attach buttons went dead with no dialog, no error, and no
12
+ way to recover without a restart. The picker now runs the synchronous dialog
13
+ in a dedicated child process (main-thread-safe, panic-isolated, watchdog at
14
+ 10 minutes). Verified live: dialog opens and returns real paths, and picker
15
+ failures now surface a toast instead of failing silently.
16
+ - Concurrent picker requests from a second client get a typed
17
+ "dialog is already open" rejection instead of queueing invisibly.
18
+
3
19
  ## 2.0.0 (2026-09-14)
4
20
 
5
21
  A major rewrite of the Skill Creator experience: model configuration rebuilt around
package/dist/cli.js CHANGED
@@ -812,7 +812,9 @@ var init_image_codec = __esm({
812
812
  });
813
813
 
814
814
  // src/daemon/agent-files.ts
815
+ import { spawn as spawn3 } from "node:child_process";
815
816
  import { readFile as readFile2, readdir, realpath, stat } from "node:fs/promises";
817
+ import { createRequire as createRequire2 } from "node:module";
816
818
  import os3 from "node:os";
817
819
  import path6 from "node:path";
818
820
  function toDomainError(error, what, target) {
@@ -854,25 +856,87 @@ function compareEntries(a, b) {
854
856
  if (a.kind !== b.kind) return a.kind === "dir" ? -1 : 1;
855
857
  return a.name.localeCompare(b.name, "en", { sensitivity: "base", numeric: true });
856
858
  }
857
- function createAgentFilesService(deps = {}) {
858
- const defaultDir = deps.defaultDir ?? (() => os3.homedir());
859
- async function pickFiles(input) {
860
- const { AsyncFileDialog } = await import("@xmorse/rfd");
861
- let builder = new AsyncFileDialog();
862
- builder = builder.setTitle(input.mode === "image" ? "Select images" : "Select files");
863
- if (input.mode === "image") {
864
- builder = builder.addFilter("Images", ["png", "jpg", "jpeg", "webp", "gif"]);
865
- }
866
- const handles = await builder.pickFiles();
867
- if (handles === null) return { paths: [] };
868
- const paths = [];
869
- for (const handle of handles) {
859
+ function resolveRfdEntry() {
860
+ if (cachedRfdEntry !== null) return cachedRfdEntry;
861
+ try {
862
+ cachedRfdEntry = createRequire2(import.meta.url).resolve("@xmorse/rfd");
863
+ } catch {
864
+ throw new DomainError("UNAVAILABLE", "native file picker runtime is not installed");
865
+ }
866
+ return cachedRfdEntry;
867
+ }
868
+ function runPickerChild(request, options2 = {}) {
869
+ const entry = options2.entry ?? resolveRfdEntry();
870
+ const timeoutMs = options2.timeoutMs ?? PICKER_TIMEOUT_MS;
871
+ const child = spawn3(process.execPath, ["-e", PICKER_CHILD_CODE, JSON.stringify(request), entry], {
872
+ stdio: ["ignore", "pipe", "pipe"],
873
+ windowsHide: true
874
+ });
875
+ return new Promise((resolve2) => {
876
+ let stdout = "";
877
+ let stderrTail = "";
878
+ const timer = setTimeout(() => {
879
+ child.kill();
880
+ resolve2({ status: "failed", message: `picker timed out after ${String(timeoutMs)}ms` });
881
+ }, timeoutMs);
882
+ child.stdout.on("data", (chunk) => {
883
+ if (stdout.length < PICKER_STDOUT_LIMIT) stdout += chunk.toString("utf8");
884
+ });
885
+ child.stderr.on("data", (chunk) => {
886
+ stderrTail = (stderrTail + chunk.toString("utf8")).slice(-300);
887
+ });
888
+ child.on("error", (error) => {
889
+ clearTimeout(timer);
890
+ resolve2({ status: "failed", message: String(error) });
891
+ });
892
+ child.on("close", (code) => {
893
+ clearTimeout(timer);
870
894
  try {
871
- paths.push(handle.path());
895
+ const parsed = JSON.parse(stdout);
896
+ if (parsed.ok === true && Array.isArray(parsed.paths)) {
897
+ const paths = parsed.paths.filter((value) => typeof value === "string");
898
+ resolve2(paths.length === 0 ? { status: "canceled" } : { status: "picked", paths });
899
+ return;
900
+ }
901
+ if (parsed.ok === false && typeof parsed.message === "string") {
902
+ resolve2({ status: "failed", message: parsed.message });
903
+ return;
904
+ }
872
905
  } catch {
873
906
  }
907
+ const detail = stderrTail.trim();
908
+ resolve2({
909
+ status: "failed",
910
+ message: `picker exited with code ${String(code)}${detail.length > 0 ? `: ${detail}` : ""}`
911
+ });
912
+ });
913
+ });
914
+ }
915
+ function createAgentFilesService(deps = {}) {
916
+ const defaultDir = deps.defaultDir ?? (() => os3.homedir());
917
+ const runNativePicker = deps.runNativePicker ?? runPickerChild;
918
+ let pickerInFlight = null;
919
+ async function pickFiles(input) {
920
+ if (pickerInFlight !== null) {
921
+ throw new DomainError("INVALID_OPERATION", "file picker dialog is already open");
922
+ }
923
+ const request = input.mode === "image" ? {
924
+ title: "Select images",
925
+ filters: [{ name: "Images", exts: ["png", "jpg", "jpeg", "webp", "gif"] }]
926
+ } : { title: "Select files", filters: [] };
927
+ const inFlight = runNativePicker(request);
928
+ pickerInFlight = inFlight;
929
+ try {
930
+ const outcome = await inFlight;
931
+ if (outcome.status === "picked") return { paths: outcome.paths ?? [] };
932
+ if (outcome.status === "canceled") return { paths: [] };
933
+ throw new DomainError(
934
+ "UNAVAILABLE",
935
+ `native file picker failed: ${outcome.message ?? "unknown error"}`
936
+ );
937
+ } finally {
938
+ if (pickerInFlight === inFlight) pickerInFlight = null;
874
939
  }
875
- return { paths };
876
940
  }
877
941
  async function list2(input) {
878
942
  const target = input.dir === void 0 ? defaultDir() : input.dir;
@@ -1022,7 +1086,7 @@ function createAgentFilesService(deps = {}) {
1022
1086
  }
1023
1087
  return { pickFiles, list: list2, preview: preview2, resolvePromptAttachments };
1024
1088
  }
1025
- var LIST_ENTRY_LIMIT, PREVIEW_IMAGE_MAX_BYTES, PREVIEW_TEXT_MAX_BYTES, PREVIEW_TEXT_HEAD_BYTES, PROMPT_IMAGE_MAX_BYTES, PROMPT_FILE_MAX_BYTES;
1089
+ var LIST_ENTRY_LIMIT, PREVIEW_IMAGE_MAX_BYTES, PREVIEW_TEXT_MAX_BYTES, PREVIEW_TEXT_HEAD_BYTES, PROMPT_IMAGE_MAX_BYTES, PROMPT_FILE_MAX_BYTES, PICKER_CHILD_CODE, PICKER_TIMEOUT_MS, PICKER_STDOUT_LIMIT, cachedRfdEntry;
1026
1090
  var init_agent_files = __esm({
1027
1091
  "src/daemon/agent-files.ts"() {
1028
1092
  "use strict";
@@ -1034,6 +1098,22 @@ var init_agent_files = __esm({
1034
1098
  PREVIEW_TEXT_HEAD_BYTES = 4096;
1035
1099
  PROMPT_IMAGE_MAX_BYTES = 4 * 1024 * 1024;
1036
1100
  PROMPT_FILE_MAX_BYTES = 512 * 1024;
1101
+ PICKER_CHILD_CODE = `"use strict";
1102
+ const write = (payload) => process.stdout.write(JSON.stringify(payload));
1103
+ try {
1104
+ const spec = JSON.parse(process.argv[1]);
1105
+ const rfd = require(process.argv[2]);
1106
+ let dialog = new rfd.FileDialog();
1107
+ if (spec.title) dialog = dialog.setTitle(spec.title);
1108
+ for (const filter of spec.filters) dialog = dialog.addFilter(filter.name, filter.exts);
1109
+ const paths = dialog.pickFiles();
1110
+ write({ ok: true, paths: Array.isArray(paths) ? paths : [] });
1111
+ } catch (error) {
1112
+ write({ ok: false, message: String((error && error.message) || error).slice(0, 300) });
1113
+ }`;
1114
+ PICKER_TIMEOUT_MS = 10 * 60 * 1e3;
1115
+ PICKER_STDOUT_LIMIT = 64 * 1024;
1116
+ cachedRfdEntry = null;
1037
1117
  }
1038
1118
  });
1039
1119
 
@@ -1327,7 +1407,7 @@ var init_creator_service = __esm({
1327
1407
  });
1328
1408
 
1329
1409
  // node_modules/.pnpm/ccski@2.5.0/node_modules/ccski/dist/create-prompt-CIJV_96B.mjs
1330
- import { createRequire as createRequire2 } from "node:module";
1410
+ import { createRequire as createRequire3 } from "node:module";
1331
1411
  import { stripVTControlCharacters } from "node:util";
1332
1412
  import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
1333
1413
  import process$1 from "node:process";
@@ -1609,7 +1689,7 @@ var init_create_prompt_CIJV_96B = __esm({
1609
1689
  value: mod,
1610
1690
  enumerable: true
1611
1691
  }) : target, mod));
1612
- __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
1692
+ __require2 = /* @__PURE__ */ createRequire3(import.meta.url);
1613
1693
  isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
1614
1694
  isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
1615
1695
  isSpaceKey = (key) => key.name === "space";
@@ -5026,7 +5106,7 @@ import { TextDecoder } from "node:util";
5026
5106
  import { homedir, tmpdir } from "node:os";
5027
5107
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
5028
5108
  import * as tty from "tty";
5029
- import { spawn as spawn3 } from "node:child_process";
5109
+ import { spawn as spawn4 } from "node:child_process";
5030
5110
  import process$12 from "node:process";
5031
5111
  import { randomUUID } from "node:crypto";
5032
5112
  import { URL as URL$1 } from "url";
@@ -6792,7 +6872,7 @@ function registerInstallCleanupHandlers() {
6792
6872
  }
6793
6873
  async function getRemoteCommitHash(repo, ref = "HEAD", timeoutMs = 3e4) {
6794
6874
  return new Promise((resolve$3, reject) => {
6795
- const child = spawn3("git", [
6875
+ const child = spawn4("git", [
6796
6876
  "ls-remote",
6797
6877
  repo,
6798
6878
  ref
@@ -6845,7 +6925,7 @@ async function gitCloneWithTimeout(repo, dest, branch, timeoutMs, output) {
6845
6925
  ];
6846
6926
  if (branch) args.push("--branch", branch);
6847
6927
  args.push(repo, dest);
6848
- const child = spawn3("git", args, { stdio: [
6928
+ const child = spawn4("git", args, { stdio: [
6849
6929
  "ignore",
6850
6930
  "pipe",
6851
6931
  "pipe"
@@ -47635,7 +47715,7 @@ var init_provider_icons_generated = __esm({
47635
47715
  // src/daemon/model-catalog.ts
47636
47716
  import fs18 from "node:fs";
47637
47717
  import path22 from "node:path";
47638
- import { createRequire as createRequire3 } from "node:module";
47718
+ import { createRequire as createRequire4 } from "node:module";
47639
47719
  function labelOf(provider) {
47640
47720
  for (const [id, label] of KNOWN_LABELS) {
47641
47721
  if (id === provider) return label;
@@ -47646,7 +47726,7 @@ function labelOf(provider) {
47646
47726
  return cn ? `${pretty} \xB7 CN` : pretty;
47647
47727
  }
47648
47728
  function resolveCatalogDataDir() {
47649
- const require2 = createRequire3(import.meta.url);
47729
+ const require2 = createRequire4(import.meta.url);
47650
47730
  const basePkg = require2.resolve("@deepseek-ai/dsh-base/package.json");
47651
47731
  const baseNm = path22.dirname(path22.dirname(path22.dirname(basePkg)));
47652
47732
  const hostReal = fs18.realpathSync(path22.join(baseNm, "@deepseek-ai/dsh-llm-pi-ai"));
@@ -48765,7 +48845,7 @@ var init_proposals = __esm({
48765
48845
  });
48766
48846
 
48767
48847
  // src/daemon/steward/jsonrpc-stdio.ts
48768
- import { spawn as spawn4 } from "node:child_process";
48848
+ import { spawn as spawn5 } from "node:child_process";
48769
48849
  function parseFrame2(raw) {
48770
48850
  let value;
48771
48851
  try {
@@ -48784,7 +48864,7 @@ function onceAbort(signal, onAbort) {
48784
48864
  return () => signal.removeEventListener("abort", listener);
48785
48865
  }
48786
48866
  function defaultStdioSpawn(command, args, options2) {
48787
- return spawn4(command, args, { cwd: options2.cwd, stdio: ["pipe", "pipe", "pipe"] });
48867
+ return spawn5(command, args, { cwd: options2.cwd, stdio: ["pipe", "pipe", "pipe"] });
48788
48868
  }
48789
48869
  function parseCommandSpec(spec) {
48790
48870
  const trimmed = spec.trim();
@@ -50376,7 +50456,7 @@ var init_skill_creator_mcp = __esm({
50376
50456
 
50377
50457
  // src/cli/cli.ts
50378
50458
  init_daemon();
50379
- import { spawn as spawn5 } from "node:child_process";
50459
+ import { spawn as spawn6 } from "node:child_process";
50380
50460
  import fs22 from "node:fs";
50381
50461
  import path28 from "node:path";
50382
50462
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -50707,7 +50787,7 @@ function spawnDaemon(webFlag = void 0) {
50707
50787
  const isTs = entry.endsWith(".ts");
50708
50788
  const baseEnv = { ...process.env };
50709
50789
  const env2 = webFlag === void 0 ? baseEnv : { ...baseEnv, [SKILL_CREATOR_WEB_ENV]: webFlag ? "1" : "0" };
50710
- const child = isTs ? spawn5("bun", [entry], { detached: true, stdio: "ignore", env: env2 }) : spawn5(process.execPath, [entry], { detached: true, stdio: "ignore", env: env2 });
50790
+ const child = isTs ? spawn6("bun", [entry], { detached: true, stdio: "ignore", env: env2 }) : spawn6(process.execPath, [entry], { detached: true, stdio: "ignore", env: env2 });
50711
50791
  child.unref();
50712
50792
  }
50713
50793
  async function ipcRequest(command, timeoutMs = 4e3, endpoint = socketPath()) {