neko-harness 0.2.2 → 0.2.3

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.
package/dist/gateway.js CHANGED
@@ -105,9 +105,9 @@ function parseGatewayArgs(argv) {
105
105
  }
106
106
 
107
107
  // packages/gateway/src/gateway.ts
108
- import { randomUUID } from "crypto";
109
- import { mkdir as mkdir2, readFile as readFile5, writeFile as writeFile2 } from "fs/promises";
110
- import { basename as basename4, dirname as dirname6, join as join9 } from "path";
108
+ import { randomUUID as randomUUID2 } from "crypto";
109
+ import { mkdir as mkdir3, readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
110
+ import { basename as basename4, dirname as dirname7, join as join10 } from "path";
111
111
  import { BACKGROUND_CONTEXT as BACKGROUND_CONTEXT2 } from "@earendil-works/chord/context";
112
112
  import { isServerId } from "@earendil-works/pi-protocol";
113
113
  import { Server, SessionNotFoundError } from "@earendil-works/pi-server";
@@ -226,6 +226,7 @@ class CompactionManager {
226
226
  import { existsSync, readFileSync } from "fs";
227
227
  import { homedir } from "os";
228
228
  import { dirname, join, resolve } from "path";
229
+ var DEFAULT_SKILL_MARKET_URL = "https://skill.kirineko.tech";
229
230
  var NEKO_CONFIG_BASENAME = "neko.config.json";
230
231
  function findNekoConfigFile(startDir = process.cwd()) {
231
232
  let dir = resolve(startDir);
@@ -328,6 +329,16 @@ function validate(config, source) {
328
329
  if (theme !== undefined && theme !== "light" && theme !== "dark" && theme !== "auto") {
329
330
  throw new Error(`neko config: ${source}: "theme" must be "light", "dark", or "auto".`);
330
331
  }
332
+ const skills = config.skills;
333
+ if (skills !== undefined) {
334
+ if (typeof skills !== "object" || skills === null) {
335
+ throw new Error(`neko config: ${source}: "skills" must be an object.`);
336
+ }
337
+ const { marketUrl } = skills;
338
+ if (marketUrl !== undefined && typeof marketUrl !== "string") {
339
+ throw new Error(`neko config: ${source}: "skills.marketUrl" must be a string.`);
340
+ }
341
+ }
331
342
  }
332
343
  // packages/core/src/credentials.ts
333
344
  import { chmod, mkdir, open, readFile, rename, unlink } from "fs/promises";
@@ -936,6 +947,32 @@ function contextTokens(entries) {
936
947
  }
937
948
  return null;
938
949
  }
950
+ // packages/core/src/prompt/frontmatter.ts
951
+ import { parse } from "yaml";
952
+ var normalizeNewlines = (value) => value.replace(/\r\n/g, `
953
+ `).replace(/\r/g, `
954
+ `);
955
+ var extractFrontmatter = (content) => {
956
+ const normalized = normalizeNewlines(content.replace(/^\uFEFF/, ""));
957
+ const opening = /^---[ \t]*\n/.exec(normalized);
958
+ if (!opening)
959
+ return { yamlString: null, body: normalized };
960
+ const rest = normalized.slice(opening[0].length);
961
+ const closing = /^---[ \t]*(?:\n|$)/m.exec(rest);
962
+ if (!closing)
963
+ return { yamlString: null, body: normalized };
964
+ return { yamlString: rest.slice(0, closing.index), body: rest.slice(closing.index + closing[0].length).trim() };
965
+ };
966
+ var parseFrontmatter = (content) => {
967
+ const { yamlString, body } = extractFrontmatter(content);
968
+ if (!yamlString)
969
+ return { frontmatter: {}, body };
970
+ const parsed = parse(yamlString);
971
+ if (parsed !== null && (typeof parsed !== "object" || Array.isArray(parsed)))
972
+ throw new Error("Frontmatter must be a YAML mapping.");
973
+ return { frontmatter: parsed ?? {}, body };
974
+ };
975
+ var stripFrontmatter = (content) => extractFrontmatter(content).body;
939
976
  // packages/core/src/runtime.ts
940
977
  import { homedir as homedir4 } from "os";
941
978
  import { join as join5 } from "path";
@@ -965,33 +1002,6 @@ var warnPromptDiagnostic = ({ path, message }) => {
965
1002
  };
966
1003
  var isMissing = (error) => typeof error === "object" && error !== null && ("code" in error) && (error.code === "ENOENT" || error.code === "ENOTDIR");
967
1004
 
968
- // packages/core/src/prompt/frontmatter.ts
969
- import { parse } from "yaml";
970
- var normalizeNewlines = (value) => value.replace(/\r\n/g, `
971
- `).replace(/\r/g, `
972
- `);
973
- var extractFrontmatter = (content) => {
974
- const normalized = normalizeNewlines(content.replace(/^\uFEFF/, ""));
975
- const opening = /^---[ \t]*\n/.exec(normalized);
976
- if (!opening)
977
- return { yamlString: null, body: normalized };
978
- const rest = normalized.slice(opening[0].length);
979
- const closing = /^---[ \t]*(?:\n|$)/m.exec(rest);
980
- if (!closing)
981
- return { yamlString: null, body: normalized };
982
- return { yamlString: rest.slice(0, closing.index), body: rest.slice(closing.index + closing[0].length).trim() };
983
- };
984
- var parseFrontmatter = (content) => {
985
- const { yamlString, body } = extractFrontmatter(content);
986
- if (!yamlString)
987
- return { frontmatter: {}, body };
988
- const parsed = parse(yamlString);
989
- if (parsed !== null && (typeof parsed !== "object" || Array.isArray(parsed)))
990
- throw new Error("Frontmatter must be a YAML mapping.");
991
- return { frontmatter: parsed ?? {}, body };
992
- };
993
- var stripFrontmatter = (content) => extractFrontmatter(content).body;
994
-
995
1005
  // packages/core/src/prompt/skills.ts
996
1006
  import { readdir, readFile as readFile2 } from "fs/promises";
997
1007
  import { basename, dirname as dirname3, join as join3 } from "path";
@@ -1185,11 +1195,13 @@ ${text}
1185
1195
  import { readFile as readFile3 } from "fs/promises";
1186
1196
  import { homedir as homedir3 } from "os";
1187
1197
  import { join as join4 } from "path";
1198
+ import { fileURLToPath } from "url";
1188
1199
  var userAgentsFile = (home) => join4(home, ".agents", "AGENTS.md");
1189
1200
  var userSkillsDir = (home) => join4(home, ".agents", "skills");
1190
1201
  var workspaceAgentsFile = (workspace) => join4(workspace, "AGENTS.md");
1191
1202
  var workspaceSkillsDir = (workspace) => join4(workspace, ".agents", "skills");
1192
- var readResources = async (workspace, home, report, invocationName) => {
1203
+ var BUILTIN_SKILLS_DIR = fileURLToPath(new URL("../../skills/", import.meta.url));
1204
+ var readResources = async (workspace, home, builtinDir, report, invocationName) => {
1193
1205
  const contextFiles = [];
1194
1206
  for (const path of [userAgentsFile(home), workspaceAgentsFile(workspace)]) {
1195
1207
  try {
@@ -1210,11 +1222,13 @@ var readResources = async (workspace, home, report, invocationName) => {
1210
1222
  if (skill.name === invocationName)
1211
1223
  candidates.set(skill.filePath, content);
1212
1224
  } : undefined;
1213
- const [user, project] = await Promise.all([
1214
- scanSkillsDir(userSkillsDir(home), report, capture),
1215
- scanSkillsDir(workspaceSkillsDir(workspace), report, capture)
1225
+ const scan = async (dir, level) => (await scanSkillsDir(dir, report, capture)).map((skill) => ({ ...skill, level }));
1226
+ const [builtin, user, project] = await Promise.all([
1227
+ builtinDir === null ? Promise.resolve([]) : scan(builtinDir, "builtin"),
1228
+ scan(userSkillsDir(home), "user"),
1229
+ scan(workspaceSkillsDir(workspace), "project")
1216
1230
  ]);
1217
- const skills = mergeSkills([user, project]);
1231
+ const skills = mergeSkills([builtin, user, project]);
1218
1232
  const winner = invocationName === undefined ? undefined : skills.find((skill) => skill.name === invocationName);
1219
1233
  if (winner && candidates) {
1220
1234
  const content = candidates.get(winner.filePath);
@@ -1223,11 +1237,12 @@ var readResources = async (workspace, home, report, invocationName) => {
1223
1237
  }
1224
1238
  return { contextFiles, skills };
1225
1239
  };
1226
- var createResourceLoader = (home = homedir3(), report = warnPromptDiagnostic) => {
1240
+ var createResourceLoader = (home = homedir3(), report = warnPromptDiagnostic, options) => {
1241
+ const builtinDir = options?.builtinDir === undefined ? BUILTIN_SKILLS_DIR : options.builtinDir;
1227
1242
  const previous = new Map;
1228
1243
  return async (workspace, invocationName) => {
1229
1244
  const diagnostics = [];
1230
- const resources = await readResources(workspace, home, (d) => diagnostics.push(d), invocationName);
1245
+ const resources = await readResources(workspace, home, builtinDir, (d) => diagnostics.push(d), invocationName);
1231
1246
  const known = previous.get(workspace);
1232
1247
  const current = new Set;
1233
1248
  for (const diagnostic of diagnostics) {
@@ -1243,6 +1258,15 @@ var createResourceLoader = (home = homedir3(), report = warnPromptDiagnostic) =>
1243
1258
  return resources;
1244
1259
  };
1245
1260
  };
1261
+ var scanSkillsByLevel = async (workspace, home = homedir3(), builtinDir = BUILTIN_SKILLS_DIR, report = warnPromptDiagnostic) => {
1262
+ const scan = async (dir, level) => (await scanSkillsDir(dir, report)).map((skill) => ({ ...skill, level }));
1263
+ const [builtin, user, project] = await Promise.all([
1264
+ builtinDir === null ? [] : scan(builtinDir, "builtin"),
1265
+ scan(userSkillsDir(home), "user"),
1266
+ scan(workspaceSkillsDir(workspace), "project")
1267
+ ]);
1268
+ return [...project, ...user, ...builtin];
1269
+ };
1246
1270
 
1247
1271
  // packages/core/src/prompt/snapshots.ts
1248
1272
  var createResourceSnapshots = (load, submission) => {
@@ -2416,7 +2440,21 @@ async function createNekoRuntime(options = {}) {
2416
2440
  const session = await sessionFor(id);
2417
2441
  const agent = await session.conversation.agent(context);
2418
2442
  const { skills } = await loadResources(savedWorkspace(agent.cwd));
2419
- return skills.map((skill) => ({ name: skill.name, description: skill.description, location: skill.filePath }));
2443
+ return skills.map((skill) => ({
2444
+ name: skill.name,
2445
+ description: skill.description,
2446
+ location: skill.filePath,
2447
+ level: skill.level
2448
+ }));
2449
+ },
2450
+ async listSkillsByLevel(cwd) {
2451
+ const skills = await scanSkillsByLevel(normalizeWorkspace(cwd ?? defaultCwd), options.promptHome ?? homedir4());
2452
+ return skills.map((skill) => ({
2453
+ name: skill.name,
2454
+ description: skill.description,
2455
+ location: skill.filePath,
2456
+ level: skill.level
2457
+ }));
2420
2458
  },
2421
2459
  installExtension(extension) {
2422
2460
  registry.install(extension);
@@ -2585,6 +2623,7 @@ var NekoChat = defineService("neko.chat");
2585
2623
  var NekoWorkspaces = defineService("neko.workspaces");
2586
2624
  var NekoCredentials = defineService("neko.credentials");
2587
2625
  var NekoWorkspaceFiles = defineService("neko.workspace-files");
2626
+ var NekoSkillMarket = defineService("neko.skill-market");
2588
2627
 
2589
2628
  // packages/gateway/src/file-search-help.ts
2590
2629
  function fileSearchInstallHelp(platform = process.platform) {
@@ -2606,10 +2645,644 @@ function fileSearchInstallHelp(platform = process.platform) {
2606
2645
  return `\u672A\u627E\u5230 fd \u6216 fdfind\uFF0C\u6682\u65F6\u65E0\u6CD5\u4F7F\u7528 @ \u6587\u4EF6\u8865\u5168\u3002\u8BF7\u5728\u8FD0\u884C neko \u7684\u7535\u8111\u4E0A\u5B89\u88C5\u3002${install}\u5B89\u88C5\u540E\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u5E76\u91CD\u542F neko\u3002`;
2607
2646
  }
2608
2647
 
2648
+ // packages/gateway/src/skill-market.ts
2649
+ import { createHash as createHash2, randomUUID } from "crypto";
2650
+ import { mkdir as mkdir2, readdir as readdir2, rename as rename2, rm as rm2, stat as stat2, writeFile as writeFile2 } from "fs/promises";
2651
+ import { homedir as homedir5 } from "os";
2652
+ import { dirname as dirname5, join as join8 } from "path";
2653
+
2654
+ // node_modules/fflate/esm/index.mjs
2655
+ import { createRequire } from "module";
2656
+ var require2 = createRequire("/");
2657
+ var _a;
2658
+ var Worker;
2659
+ var isMarkedAsUntransferable;
2660
+ try {
2661
+ _a = require2("worker_threads"), Worker = _a.Worker, isMarkedAsUntransferable = _a.isMarkedAsUntransferable;
2662
+ } catch (e) {}
2663
+ var u8 = Uint8Array;
2664
+ var u16 = Uint16Array;
2665
+ var i32 = Int32Array;
2666
+ var fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0]);
2667
+ var fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0]);
2668
+ var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
2669
+ var freb = function(eb, start) {
2670
+ var b = new u16(31);
2671
+ for (var i = 0;i < 31; ++i) {
2672
+ b[i] = start += 1 << eb[i - 1];
2673
+ }
2674
+ var r = new i32(b[30]);
2675
+ for (var i = 1;i < 30; ++i) {
2676
+ for (var j = b[i];j < b[i + 1]; ++j) {
2677
+ r[j] = j - b[i] << 5 | i;
2678
+ }
2679
+ }
2680
+ return { b, r };
2681
+ };
2682
+ var _a = freb(fleb, 2);
2683
+ var fl = _a.b;
2684
+ var revfl = _a.r;
2685
+ fl[28] = 258, revfl[258] = 28;
2686
+ var _b = freb(fdeb, 0);
2687
+ var fd = _b.b;
2688
+ var revfd = _b.r;
2689
+ var rev = new u16(32768);
2690
+ for (i = 0;i < 32768; ++i) {
2691
+ x = (i & 43690) >> 1 | (i & 21845) << 1;
2692
+ x = (x & 52428) >> 2 | (x & 13107) << 2;
2693
+ x = (x & 61680) >> 4 | (x & 3855) << 4;
2694
+ rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
2695
+ }
2696
+ var x;
2697
+ var i;
2698
+ var hMap = function(cd, mb, r) {
2699
+ var s = cd.length;
2700
+ var i = 0;
2701
+ var l = new u16(mb);
2702
+ for (;i < s; ++i) {
2703
+ if (cd[i])
2704
+ ++l[cd[i] - 1];
2705
+ }
2706
+ var le = new u16(mb);
2707
+ for (i = 1;i < mb; ++i) {
2708
+ le[i] = le[i - 1] + l[i - 1] << 1;
2709
+ }
2710
+ var co;
2711
+ if (r) {
2712
+ co = new u16(1 << mb);
2713
+ var rvb = 15 - mb;
2714
+ for (i = 0;i < s; ++i) {
2715
+ if (cd[i]) {
2716
+ var sv = i << 4 | cd[i];
2717
+ var r_1 = mb - cd[i];
2718
+ var v = le[cd[i] - 1]++ << r_1;
2719
+ for (var m = v | (1 << r_1) - 1;v <= m; ++v) {
2720
+ co[rev[v] >> rvb] = sv;
2721
+ }
2722
+ }
2723
+ }
2724
+ } else {
2725
+ co = new u16(s);
2726
+ for (i = 0;i < s; ++i) {
2727
+ if (cd[i]) {
2728
+ co[i] = rev[le[cd[i] - 1]++] >> 15 - cd[i];
2729
+ }
2730
+ }
2731
+ }
2732
+ return co;
2733
+ };
2734
+ var flt = new u8(288);
2735
+ for (i = 0;i < 144; ++i)
2736
+ flt[i] = 8;
2737
+ var i;
2738
+ for (i = 144;i < 256; ++i)
2739
+ flt[i] = 9;
2740
+ var i;
2741
+ for (i = 256;i < 280; ++i)
2742
+ flt[i] = 7;
2743
+ var i;
2744
+ for (i = 280;i < 288; ++i)
2745
+ flt[i] = 8;
2746
+ var i;
2747
+ var fdt = new u8(32);
2748
+ for (i = 0;i < 32; ++i)
2749
+ fdt[i] = 5;
2750
+ var i;
2751
+ var flrm = /* @__PURE__ */ hMap(flt, 9, 1);
2752
+ var fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
2753
+ var max = function(a) {
2754
+ var m = a[0];
2755
+ for (var i = 1;i < a.length; ++i) {
2756
+ if (a[i] > m)
2757
+ m = a[i];
2758
+ }
2759
+ return m;
2760
+ };
2761
+ var bits = function(d, p, m) {
2762
+ var o = p / 8 | 0;
2763
+ return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
2764
+ };
2765
+ var bits16 = function(d, p) {
2766
+ var o = p / 8 | 0;
2767
+ return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
2768
+ };
2769
+ var shft = function(p) {
2770
+ return (p + 7) / 8 | 0;
2771
+ };
2772
+ var slc = function(v, s, e) {
2773
+ if (s == null || s < 0)
2774
+ s = 0;
2775
+ if (e == null || e > v.length)
2776
+ e = v.length;
2777
+ return new u8(v.subarray(s, e));
2778
+ };
2779
+ var ec = [
2780
+ "unexpected EOF",
2781
+ "invalid block type",
2782
+ "invalid length/literal",
2783
+ "invalid distance",
2784
+ "stream finished",
2785
+ "no stream handler",
2786
+ ,
2787
+ "no callback",
2788
+ "invalid UTF-8 data",
2789
+ "extra field too long",
2790
+ "date not in range 1980-2099",
2791
+ "filename too long",
2792
+ "stream finishing",
2793
+ "invalid zip data"
2794
+ ];
2795
+ var err = function(ind, msg, nt) {
2796
+ var e = new Error(msg || ec[ind]);
2797
+ e.code = ind;
2798
+ if (Error.captureStackTrace)
2799
+ Error.captureStackTrace(e, err);
2800
+ if (!nt)
2801
+ throw e;
2802
+ return e;
2803
+ };
2804
+ var inflt = function(dat, st, buf, dict) {
2805
+ var sl = dat.length, dl = dict ? dict.length : 0;
2806
+ if (!sl || st.f && !st.l)
2807
+ return buf || new u8(0);
2808
+ var noBuf = !buf;
2809
+ var resize = noBuf || st.i != 2;
2810
+ var noSt = st.i;
2811
+ if (noBuf)
2812
+ buf = new u8(sl * 3);
2813
+ var cbuf = function(l) {
2814
+ var bl = buf.length;
2815
+ if (l > bl) {
2816
+ var nbuf = new u8(Math.max(bl * 2, l));
2817
+ nbuf.set(buf);
2818
+ buf = nbuf;
2819
+ }
2820
+ };
2821
+ var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, { l: lm, d: dm, m: lbt, n: dbt } = st;
2822
+ var tbts = sl * 8;
2823
+ do {
2824
+ if (!lm) {
2825
+ final = bits(dat, pos, 1);
2826
+ var type = bits(dat, pos + 1, 3);
2827
+ pos += 3;
2828
+ if (!type) {
2829
+ var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
2830
+ if (t > sl) {
2831
+ if (noSt)
2832
+ err(0);
2833
+ break;
2834
+ }
2835
+ if (resize)
2836
+ cbuf(bt + l);
2837
+ buf.set(dat.subarray(s, t), bt);
2838
+ st.b = bt += l, st.p = pos = t * 8, st.f = final;
2839
+ continue;
2840
+ } else if (type == 1)
2841
+ lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
2842
+ else if (type == 2) {
2843
+ var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
2844
+ var tl = hLit + bits(dat, pos + 5, 31) + 1;
2845
+ pos += 14;
2846
+ var ldt = new u8(tl);
2847
+ var clt = new u8(19);
2848
+ for (var i = 0;i < hcLen; ++i) {
2849
+ clt[clim[i]] = bits(dat, pos + i * 3, 7);
2850
+ }
2851
+ pos += hcLen * 3;
2852
+ var clb = max(clt), clbmsk = (1 << clb) - 1;
2853
+ var clm = hMap(clt, clb, 1);
2854
+ for (var i = 0;i < tl; ) {
2855
+ var r = clm[bits(dat, pos, clbmsk)];
2856
+ pos += r & 15;
2857
+ var s = r >> 4;
2858
+ if (s < 16) {
2859
+ ldt[i++] = s;
2860
+ } else {
2861
+ var c = 0, n = 0;
2862
+ if (s == 16)
2863
+ n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
2864
+ else if (s == 17)
2865
+ n = 3 + bits(dat, pos, 7), pos += 3;
2866
+ else if (s == 18)
2867
+ n = 11 + bits(dat, pos, 127), pos += 7;
2868
+ while (n--)
2869
+ ldt[i++] = c;
2870
+ }
2871
+ }
2872
+ var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
2873
+ lbt = max(lt);
2874
+ dbt = max(dt);
2875
+ lm = hMap(lt, lbt, 1);
2876
+ dm = hMap(dt, dbt, 1);
2877
+ } else
2878
+ err(1);
2879
+ if (pos > tbts) {
2880
+ if (noSt)
2881
+ err(0);
2882
+ break;
2883
+ }
2884
+ }
2885
+ if (resize)
2886
+ cbuf(bt + 131072);
2887
+ var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
2888
+ var lpos = pos;
2889
+ for (;; lpos = pos) {
2890
+ var c = lm[bits16(dat, pos) & lms], sym = c >> 4;
2891
+ pos += c & 15;
2892
+ if (pos > tbts) {
2893
+ if (noSt)
2894
+ err(0);
2895
+ break;
2896
+ }
2897
+ if (!c)
2898
+ err(2);
2899
+ if (sym < 256)
2900
+ buf[bt++] = sym;
2901
+ else if (sym == 256) {
2902
+ lpos = pos, lm = null;
2903
+ break;
2904
+ } else {
2905
+ var add = sym - 254;
2906
+ if (sym > 264) {
2907
+ var i = sym - 257, b = fleb[i];
2908
+ add = bits(dat, pos, (1 << b) - 1) + fl[i];
2909
+ pos += b;
2910
+ }
2911
+ var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
2912
+ if (!d)
2913
+ err(3);
2914
+ pos += d & 15;
2915
+ var dt = fd[dsym];
2916
+ if (dsym > 3) {
2917
+ var b = fdeb[dsym];
2918
+ dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
2919
+ }
2920
+ if (pos > tbts) {
2921
+ if (noSt)
2922
+ err(0);
2923
+ break;
2924
+ }
2925
+ if (resize)
2926
+ cbuf(bt + 131072);
2927
+ var end = bt + add;
2928
+ if (bt < dt) {
2929
+ var shift = dl - dt, dend = Math.min(dt, end);
2930
+ if (shift + bt < 0)
2931
+ err(3);
2932
+ for (;bt < dend; ++bt)
2933
+ buf[bt] = dict[shift + bt];
2934
+ }
2935
+ for (;bt < end; ++bt)
2936
+ buf[bt] = buf[bt - dt];
2937
+ }
2938
+ }
2939
+ st.l = lm, st.p = lpos, st.b = bt, st.f = final;
2940
+ if (lm)
2941
+ final = 1, st.m = lbt, st.d = dm, st.n = dbt;
2942
+ } while (!final);
2943
+ return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);
2944
+ };
2945
+ var et = /* @__PURE__ */ new u8(0);
2946
+ var b2 = function(d, b) {
2947
+ return d[b] | d[b + 1] << 8;
2948
+ };
2949
+ var b4 = function(d, b) {
2950
+ return (d[b] | d[b + 1] << 8 | d[b + 2] << 16 | d[b + 3] << 24) >>> 0;
2951
+ };
2952
+ var b8 = function(d, b) {
2953
+ return b4(d, b) + b4(d, b + 4) * 4294967296;
2954
+ };
2955
+ function inflateSync(data, opts) {
2956
+ return inflt(data, { i: 2 }, opts && opts.out, opts && opts.dictionary);
2957
+ }
2958
+ var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder;
2959
+ var tds = 0;
2960
+ try {
2961
+ td.decode(et, { stream: true });
2962
+ tds = 1;
2963
+ } catch (e) {}
2964
+ var dutf8 = function(d) {
2965
+ for (var r = "", i = 0;; ) {
2966
+ var c = d[i++];
2967
+ var eb = (c > 127) + (c > 223) + (c > 239);
2968
+ if (i + eb > d.length)
2969
+ return { s: r, r: slc(d, i - 1) };
2970
+ if (!eb)
2971
+ r += String.fromCharCode(c);
2972
+ else if (eb == 3) {
2973
+ c = ((c & 15) << 18 | (d[i++] & 63) << 12 | (d[i++] & 63) << 6 | d[i++] & 63) - 65536, r += String.fromCharCode(55296 | c >> 10, 56320 | c & 1023);
2974
+ } else if (eb & 1)
2975
+ r += String.fromCharCode((c & 31) << 6 | d[i++] & 63);
2976
+ else
2977
+ r += String.fromCharCode((c & 15) << 12 | (d[i++] & 63) << 6 | d[i++] & 63);
2978
+ }
2979
+ };
2980
+ function strFromU8(dat, latin1) {
2981
+ if (latin1) {
2982
+ var r = "";
2983
+ for (var i = 0;i < dat.length; i += 16384)
2984
+ r += String.fromCharCode.apply(null, dat.subarray(i, i + 16384));
2985
+ return r;
2986
+ } else if (td) {
2987
+ return td.decode(dat);
2988
+ } else {
2989
+ var _a = dutf8(dat), { s, r } = _a;
2990
+ if (r.length)
2991
+ err(8);
2992
+ return s;
2993
+ }
2994
+ }
2995
+ var slzh = function(d, b) {
2996
+ return b + 30 + b2(d, b + 26) + b2(d, b + 28);
2997
+ };
2998
+ var zh = function(d, b, z) {
2999
+ var fnl = b2(d, b + 28), efl = b2(d, b + 30), fn = strFromU8(d.subarray(b + 46, b + 46 + fnl), !(b2(d, b + 8) & 2048)), es = b + 46 + fnl;
3000
+ var _a = z64hs(d, es, efl, z, b4(d, b + 20), b4(d, b + 24), b4(d, b + 42)), sc = _a[0], su = _a[1], off = _a[2];
3001
+ return [b2(d, b + 10), sc, su, fn, es + efl + b2(d, b + 32), off];
3002
+ };
3003
+ var z64hs = function(d, b, l, z, sc, su, off) {
3004
+ var nsc = sc == 4294967295, nsu = su == 4294967295, noff = off == 4294967295, e = b + l;
3005
+ var nf = nsc + nsu + noff;
3006
+ if (z && nf) {
3007
+ for (;b + 4 < e; b += 4 + b2(d, b + 2)) {
3008
+ if (b2(d, b) == 1) {
3009
+ return [
3010
+ nsc ? b8(d, b + 4 + 8 * nsu) : sc,
3011
+ nsu ? b8(d, b + 4) : su,
3012
+ noff ? b8(d, b + 4 + 8 * (nsu + nsc)) : off,
3013
+ 1
3014
+ ];
3015
+ }
3016
+ }
3017
+ if (z < 2)
3018
+ err(13);
3019
+ }
3020
+ return [sc, su, off, 0];
3021
+ };
3022
+ function unzipSync(data, opts) {
3023
+ var files = {};
3024
+ var e = data.length - 22;
3025
+ for (;b4(data, e) != 101010256; --e) {
3026
+ if (!e || data.length - e > 65558)
3027
+ err(13);
3028
+ }
3029
+ var c = b2(data, e + 8);
3030
+ if (!c)
3031
+ return {};
3032
+ var o = b4(data, e + 16);
3033
+ var z = b4(data, e - 20) == 117853008;
3034
+ if (z) {
3035
+ var ze = b4(data, e - 12);
3036
+ z = b4(data, ze) == 101075792;
3037
+ if (z) {
3038
+ c = b4(data, ze + 32);
3039
+ o = b4(data, ze + 48);
3040
+ }
3041
+ }
3042
+ var fltr = opts && opts.filter;
3043
+ for (var i = 0;i < c; ++i) {
3044
+ var _a = zh(data, o, z), c_2 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off);
3045
+ o = no;
3046
+ if (!fltr || fltr({
3047
+ name: fn,
3048
+ size: sc,
3049
+ originalSize: su,
3050
+ compression: c_2
3051
+ })) {
3052
+ if (!c_2)
3053
+ files[fn] = slc(data, b, b + sc);
3054
+ else if (c_2 == 8)
3055
+ files[fn] = inflateSync(data.subarray(b, b + sc), { out: new u8(su) });
3056
+ else
3057
+ err(14, "unknown compression type " + c_2);
3058
+ }
3059
+ }
3060
+ return files;
3061
+ }
3062
+
3063
+ // packages/gateway/src/skill-market.ts
3064
+ class SkillMarketError extends Error {
3065
+ code;
3066
+ constructor(code, message) {
3067
+ super(message);
3068
+ this.name = "SkillMarketError";
3069
+ this.code = code;
3070
+ }
3071
+ }
3072
+ var CATALOG_TTL_MS = 60000;
3073
+ var ZIP_CACHE_MAX = 16;
3074
+ var MAX_PACKAGE_BYTES = 32 * 1024 * 1024;
3075
+ var userSkillsDir2 = (home) => join8(home, ".agents", "skills");
3076
+ var projectSkillsDir = (workspaceRoot) => join8(workspaceRoot, ".agents", "skills");
3077
+ var activeLevelOf = (state) => state.project ? "project" : state.user ? "user" : state.builtin ? "builtin" : null;
3078
+ var normalizeEntry = (raw) => {
3079
+ const row = raw ?? {};
3080
+ const metadata = row.metadata;
3081
+ const source = metadata !== null && typeof metadata === "object" ? metadata.source : undefined;
3082
+ return {
3083
+ name: String(row.name ?? ""),
3084
+ description: String(row.description ?? ""),
3085
+ category: typeof row.category === "string" && row.category !== "" ? row.category : "uncategorized",
3086
+ source: typeof source === "string" && source !== "" ? source : "unknown",
3087
+ license: String(row.license ?? ""),
3088
+ version: String(row.version ?? ""),
3089
+ sha256: String(row.sha256 ?? ""),
3090
+ sizeBytes: Number(row.size_bytes ?? 0),
3091
+ uploadedAt: String(row.uploaded_at ?? "")
3092
+ };
3093
+ };
3094
+ function createSkillMarketClient(options) {
3095
+ const home = options.home ?? homedir5();
3096
+ const fetchImpl = options.fetchImpl ?? fetch;
3097
+ const now = options.now ?? Date.now;
3098
+ let base;
3099
+ try {
3100
+ base = new URL(options.marketUrl);
3101
+ if (base.protocol !== "https:" && base.protocol !== "http:")
3102
+ throw new Error("unsupported protocol");
3103
+ } catch {
3104
+ throw new SkillMarketError("market_invalid_url", `Invalid skill market URL: ${options.marketUrl}`);
3105
+ }
3106
+ base = new URL(base.toString().replace(/\/+$/, ""));
3107
+ let catalog;
3108
+ const zipCache = new Map;
3109
+ const request = async (path) => {
3110
+ let response;
3111
+ try {
3112
+ response = await fetchImpl(new URL(path, `${base}/`).toString());
3113
+ } catch (error) {
3114
+ throw new SkillMarketError("market_unavailable", `Skill market unreachable: ${error instanceof Error ? error.message : String(error)}`);
3115
+ }
3116
+ return response;
3117
+ };
3118
+ const refreshCatalog = async () => {
3119
+ const response = await request("api/skills");
3120
+ if (!response.ok)
3121
+ throw new SkillMarketError("market_unavailable", `Skill list failed with HTTP ${response.status}`);
3122
+ const data = await response.json();
3123
+ const skills = Array.isArray(data.skills) ? data.skills.map(normalizeEntry) : [];
3124
+ catalog = { at: now(), skills };
3125
+ return skills;
3126
+ };
3127
+ const listSkills = async () => catalog !== undefined && now() - catalog.at < CATALOG_TTL_MS ? catalog.skills : refreshCatalog();
3128
+ const detail = async (name) => {
3129
+ let hit = (await listSkills()).find((skill) => skill.name === name);
3130
+ if (hit === undefined)
3131
+ hit = (await refreshCatalog()).find((skill) => skill.name === name);
3132
+ if (hit === undefined)
3133
+ throw new SkillMarketError("skill_not_found", `Skill not found on market: ${name}`);
3134
+ return hit;
3135
+ };
3136
+ const download = async (skill) => {
3137
+ const cached = zipCache.get(skill.sha256);
3138
+ if (cached !== undefined) {
3139
+ zipCache.delete(skill.sha256);
3140
+ zipCache.set(skill.sha256, cached);
3141
+ return cached;
3142
+ }
3143
+ if (skill.sizeBytes > MAX_PACKAGE_BYTES)
3144
+ throw new SkillMarketError("skill_too_large", `Package ${skill.name} is ${skill.sizeBytes} bytes (limit ${MAX_PACKAGE_BYTES})`);
3145
+ const response = await request(`api/skills/${encodeURIComponent(skill.name)}/download`);
3146
+ if (!response.ok)
3147
+ throw new SkillMarketError(response.status === 404 ? "skill_not_found" : "market_unavailable", `Download of ${skill.name} failed with HTTP ${response.status}`);
3148
+ const bytes = new Uint8Array(await response.arrayBuffer());
3149
+ if (bytes.byteLength > MAX_PACKAGE_BYTES)
3150
+ throw new SkillMarketError("skill_too_large", `Package ${skill.name} exceeds ${MAX_PACKAGE_BYTES} bytes`);
3151
+ const digest = createHash2("sha256").update(bytes).digest("hex");
3152
+ if (digest !== skill.sha256)
3153
+ throw new SkillMarketError("skill_hash_mismatch", `SHA-256 mismatch for ${skill.name}: catalog says ${skill.sha256}, got ${digest}`);
3154
+ zipCache.set(skill.sha256, bytes);
3155
+ while (zipCache.size > ZIP_CACHE_MAX) {
3156
+ const oldest = zipCache.keys().next().value;
3157
+ if (oldest === undefined)
3158
+ break;
3159
+ zipCache.delete(oldest);
3160
+ }
3161
+ return bytes;
3162
+ };
3163
+ const unpack = (skill, zip) => {
3164
+ let entries;
3165
+ try {
3166
+ entries = unzipSync(zip);
3167
+ } catch {
3168
+ throw new SkillMarketError("skill_invalid_package", `Package ${skill.name} is not a valid zip archive`);
3169
+ }
3170
+ const files = new Map;
3171
+ const skillMds = [];
3172
+ for (const name of Object.keys(entries)) {
3173
+ if (name.endsWith("/"))
3174
+ continue;
3175
+ if (name.includes("\\") || name.startsWith("/"))
3176
+ throw new SkillMarketError("skill_invalid_package", `Unsafe path in package: ${name}`);
3177
+ const segments = name.split("/");
3178
+ if (segments.some((s) => s === ".." || s === ""))
3179
+ throw new SkillMarketError("skill_invalid_package", `Unsafe path in package: ${name}`);
3180
+ if (segments[segments.length - 1] === "SKILL.md")
3181
+ skillMds.push(name);
3182
+ files.set(name, entries[name]);
3183
+ }
3184
+ if (skillMds.length !== 1)
3185
+ throw new SkillMarketError("skill_invalid_package", skillMds.length === 0 ? `Package ${skill.name} contains no SKILL.md` : `Package ${skill.name} contains multiple SKILL.md files`);
3186
+ const root = skillMds[0].slice(0, -"SKILL.md".length);
3187
+ const inner = new Map;
3188
+ for (const [name, bytes] of files) {
3189
+ if (!name.startsWith(root))
3190
+ continue;
3191
+ inner.set(name.slice(root.length), bytes);
3192
+ }
3193
+ return inner;
3194
+ };
3195
+ const skillsDirFor = (scope, workspaceRoot) => {
3196
+ if (scope === "user")
3197
+ return userSkillsDir2(home);
3198
+ if (workspaceRoot === undefined || workspaceRoot === "")
3199
+ throw new SkillMarketError("market_unavailable", "Project-scope install needs a workspaceRoot");
3200
+ return projectSkillsDir(workspaceRoot);
3201
+ };
3202
+ const sweepTempDirs = async (skillsDir) => {
3203
+ const parent = dirname5(skillsDir);
3204
+ let names = [];
3205
+ try {
3206
+ names = await readdir2(parent);
3207
+ } catch {
3208
+ return;
3209
+ }
3210
+ await Promise.all(names.filter((n) => n.startsWith(".tmp-")).map((n) => rm2(join8(parent, n), { recursive: true, force: true }).catch(() => {})));
3211
+ };
3212
+ const install = async ({ name, scope, workspaceRoot, overwrite }) => {
3213
+ const skillsDir = skillsDirFor(scope, workspaceRoot);
3214
+ const target = join8(skillsDir, name);
3215
+ const exists = await stat2(target).catch(() => {
3216
+ return;
3217
+ }) !== undefined;
3218
+ if (exists && overwrite !== true)
3219
+ throw new SkillMarketError("skill_exists", `Skill ${name} already exists at ${scope} level (${target})`);
3220
+ const skill = await detail(name);
3221
+ const files = unpack(skill, await download(skill));
3222
+ await sweepTempDirs(skillsDir);
3223
+ const temp = join8(dirname5(skillsDir), `.tmp-${randomUUID()}`);
3224
+ try {
3225
+ for (const [relative, bytes] of files) {
3226
+ const dest = join8(temp, ...relative.split("/"));
3227
+ await mkdir2(dirname5(dest), { recursive: true });
3228
+ await writeFile2(dest, bytes);
3229
+ }
3230
+ if (exists)
3231
+ await rm2(target, { recursive: true, force: true });
3232
+ await mkdir2(skillsDir, { recursive: true });
3233
+ await rename2(temp, target);
3234
+ } finally {
3235
+ await rm2(temp, { recursive: true, force: true }).catch(() => {});
3236
+ }
3237
+ let shadowedBy;
3238
+ if (scope === "user" && workspaceRoot !== undefined && workspaceRoot !== "") {
3239
+ const projectDir = join8(projectSkillsDir(workspaceRoot), name);
3240
+ if (await stat2(projectDir).catch(() => {
3241
+ return;
3242
+ }) !== undefined)
3243
+ shadowedBy = "project";
3244
+ }
3245
+ return { name, scope, path: target, ...shadowedBy !== undefined ? { shadowedBy } : {} };
3246
+ };
3247
+ const uninstall = async ({ name, scope, workspaceRoot }) => {
3248
+ const skillsDir = skillsDirFor(scope, workspaceRoot);
3249
+ const target = join8(skillsDir, name);
3250
+ if (await stat2(target).catch(() => {
3251
+ return;
3252
+ }) === undefined)
3253
+ throw new SkillMarketError("skill_not_installed", `Skill ${name} is not installed at ${scope} level`);
3254
+ await rm2(target, { recursive: true, force: true });
3255
+ };
3256
+ return {
3257
+ async list(query) {
3258
+ if (query !== undefined && query.trim() !== "") {
3259
+ const response = await request(`api/skills?q=${encodeURIComponent(query.trim())}`);
3260
+ if (!response.ok)
3261
+ throw new SkillMarketError("market_unavailable", `Skill search failed with HTTP ${response.status}`);
3262
+ const data = await response.json();
3263
+ return Array.isArray(data.skills) ? data.skills.map(normalizeEntry) : [];
3264
+ }
3265
+ return listSkills();
3266
+ },
3267
+ detail,
3268
+ async preview(name) {
3269
+ const skill = await detail(name);
3270
+ const inner = unpack(skill, await download(skill));
3271
+ const bodyBytes = inner.get("SKILL.md");
3272
+ if (bodyBytes === undefined)
3273
+ throw new SkillMarketError("skill_invalid_package", `Package ${name} lost its SKILL.md`);
3274
+ const body = stripFrontmatter(new TextDecoder().decode(bodyBytes));
3275
+ return { body, files: [...inner.keys()].sort() };
3276
+ },
3277
+ install,
3278
+ uninstall
3279
+ };
3280
+ }
3281
+
2609
3282
  // packages/gateway/src/workspaces.ts
2610
3283
  import { constants as constants3 } from "fs";
2611
- import { access, readdir as readdir2, stat as stat2 } from "fs/promises";
2612
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join8 } from "path";
3284
+ import { access, readdir as readdir3, stat as stat3 } from "fs/promises";
3285
+ import { dirname as dirname6, isAbsolute as isAbsolute3, join as join9 } from "path";
2613
3286
  async function browseWorkspaces(options) {
2614
3287
  const requested = options.path.replace(/^\/+([A-Za-z]:[\\/])/, "$1");
2615
3288
  if (process.platform === "win32" && (requested === "/" || requested === "\\")) {
@@ -2631,16 +3304,16 @@ async function browseWorkspaces(options) {
2631
3304
  throw new Error("\u76EE\u5F55\u5206\u9875\u5DF2\u5931\u6548\uFF0C\u8BF7\u5237\u65B0\u5217\u8868");
2632
3305
  }
2633
3306
  }
2634
- const entries = (await readdir2(path, { withFileTypes: true })).filter((entry) => (options.showHidden || !entry.name.startsWith(".")) && entry.name.toLowerCase().includes(query)).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
3307
+ const entries = (await readdir3(path, { withFileTypes: true })).filter((entry) => (options.showHidden || !entry.name.startsWith(".")) && entry.name.toLowerCase().includes(query)).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
2635
3308
  const directories = [];
2636
3309
  let next = offset;
2637
3310
  for (;next < entries.length && directories.length < 100; next++) {
2638
3311
  const entry = entries[next];
2639
- const target = join8(path, entry.name);
3312
+ const target = join9(path, entry.name);
2640
3313
  if (!entry.isDirectory() && !entry.isSymbolicLink())
2641
3314
  continue;
2642
3315
  try {
2643
- if (!(await stat2(target)).isDirectory())
3316
+ if (!(await stat3(target)).isDirectory())
2644
3317
  continue;
2645
3318
  await access(target, constants3.R_OK | constants3.X_OK);
2646
3319
  directories.push({ name: entry.name, path: target });
@@ -2650,7 +3323,7 @@ async function browseWorkspaces(options) {
2650
3323
  }
2651
3324
  return {
2652
3325
  path,
2653
- parent: dirname5(path) === path ? null : dirname5(path),
3326
+ parent: dirname6(path) === path ? null : dirname6(path),
2654
3327
  entries: directories,
2655
3328
  next: next < entries.length ? JSON.stringify({ key, offset: next }) : null
2656
3329
  };
@@ -2670,6 +3343,26 @@ async function listDrives() {
2670
3343
  // packages/gateway/src/server-services.ts
2671
3344
  async function createNekoServerServices(options) {
2672
3345
  const { runtime, context } = options;
3346
+ const market = createSkillMarketClient({
3347
+ marketUrl: options.marketUrl,
3348
+ ...options.promptHome !== undefined ? { home: options.promptHome } : {}
3349
+ });
3350
+ const toRemote = (error) => {
3351
+ if (error instanceof SkillMarketError) {
3352
+ const code = error.code === "skill_not_found" || error.code === "skill_not_installed" ? "service_not_found" : "service_invalid_value";
3353
+ throw new RemoteServiceError(code, `[${error.code}] ${error.message}`);
3354
+ }
3355
+ throw error;
3356
+ };
3357
+ const withInstallState = async (skill, workspaceRoot) => {
3358
+ const locals = await runtime.listSkillsByLevel(workspaceRoot);
3359
+ const installed = {
3360
+ project: locals.some((s) => s.name === skill.name && s.level === "project"),
3361
+ user: locals.some((s) => s.name === skill.name && s.level === "user"),
3362
+ builtin: locals.some((s) => s.name === skill.name && s.level === "builtin")
3363
+ };
3364
+ return { ...skill, installed, activeLevel: activeLevelOf(installed) };
3365
+ };
2673
3366
  const list = async () => (await runtime.listConversations()).map((info) => ({
2674
3367
  id: String(info.id),
2675
3368
  workspaceRoot: info.workspaceRoot,
@@ -2725,7 +3418,8 @@ async function createNekoServerServices(options) {
2725
3418
  { service: NekoModels, mode: "singleton" },
2726
3419
  { service: NekoCredentials, mode: "singleton" },
2727
3420
  { service: NekoWorkspaces, mode: "singleton" },
2728
- { service: NekoWorkspaceFiles, mode: "singleton" }
3421
+ { service: NekoWorkspaceFiles, mode: "singleton" },
3422
+ { service: NekoSkillMarket, mode: "singleton" }
2729
3423
  ]);
2730
3424
  provider.provide(NekoSessionDirectory, { state: directory });
2731
3425
  const updateCredentials = (operation) => serialize(async () => {
@@ -2775,6 +3469,13 @@ async function createNekoServerServices(options) {
2775
3469
  }
2776
3470
  });
2777
3471
  provider.provide(NekoModels, { list: async () => runtime.listModels() });
3472
+ provider.provide(NekoSkillMarket, {
3473
+ list: (input) => market.list(input.query).then((skills) => Promise.all(skills.map((skill) => withInstallState(skill, input.workspaceRoot)))).catch(toRemote),
3474
+ detail: (input) => market.detail(input.name).then((skill) => withInstallState(skill, input.workspaceRoot)).catch(toRemote),
3475
+ preview: (input) => market.preview(input.name).catch(toRemote),
3476
+ install: (input) => serialize(() => market.install(input).then((result) => ({ ...result })).catch(toRemote)),
3477
+ uninstall: (input) => serialize(() => market.uninstall(input).catch(toRemote))
3478
+ });
2778
3479
  provider.provide(NekoSessionManagement, {
2779
3480
  create: (createOptions) => serialize(async () => {
2780
3481
  const created = await runtime.createConversation(createOptions.model !== undefined || createOptions.thinkingLevel !== undefined || createOptions.cwd !== undefined ? {
@@ -3293,9 +3994,10 @@ async function startGateway(options = {}) {
3293
3994
  const storagePath = options.storagePath ?? fileConfig.storagePath ?? DEFAULT_STORAGE_PATH;
3294
3995
  const host = options.host ?? fileConfig.gateway?.host ?? DEFAULT_HOST;
3295
3996
  const port = options.port !== undefined ? options.port : fileConfig.gateway?.port ?? (process.platform === "win32" ? 0 : DEFAULT_PORT);
3296
- const nekoDir = dirname6(storagePath);
3997
+ const marketUrl = options.marketUrl ?? fileConfig.skills?.marketUrl ?? DEFAULT_SKILL_MARKET_URL;
3998
+ const nekoDir = dirname7(storagePath);
3297
3999
  const serverId = options.serverId ?? await loadOrCreateServerId(nekoDir);
3298
- const socketPath = options.socketPath !== undefined ? options.socketPath : fileConfig.gateway?.socketPath !== undefined ? fileConfig.gateway.socketPath : process.platform === "win32" ? null : join9(nekoDir, `${serverId}.sock`);
4000
+ const socketPath = options.socketPath !== undefined ? options.socketPath : fileConfig.gateway?.socketPath !== undefined ? fileConfig.gateway.socketPath : process.platform === "win32" ? null : join10(nekoDir, `${serverId}.sock`);
3299
4001
  const runtime = await createNekoRuntime({
3300
4002
  context,
3301
4003
  storage: options.storage ?? "sqlite",
@@ -3318,6 +4020,8 @@ async function startGateway(options = {}) {
3318
4020
  serverId,
3319
4021
  nekoDir,
3320
4022
  model,
4023
+ marketUrl,
4024
+ promptHome: options.promptHome,
3321
4025
  onError: options.onError
3322
4026
  });
3323
4027
  } catch (error) {
@@ -3328,7 +4032,12 @@ async function startGateway(options = {}) {
3328
4032
  async function bindGateway(runtime, options) {
3329
4033
  const { context, host, port, socketPath, serverId, nekoDir, model } = options;
3330
4034
  const modelLabel = `${model.provider}/${model.modelId}`;
3331
- const serverServices = await createNekoServerServices({ runtime, context });
4035
+ const serverServices = await createNekoServerServices({
4036
+ runtime,
4037
+ context,
4038
+ marketUrl: options.marketUrl,
4039
+ ...options.promptHome !== undefined ? { promptHome: options.promptHome } : {}
4040
+ });
3332
4041
  let wsListener;
3333
4042
  const listeners = [];
3334
4043
  if (socketPath !== null) {
@@ -3406,15 +4115,15 @@ function serverIdFromSocketPath(socketPath) {
3406
4115
  return isServerId(candidate) ? candidate : undefined;
3407
4116
  }
3408
4117
  async function loadOrCreateServerId(nekoDir) {
3409
- const file = join9(nekoDir, SERVER_ID_FILENAME);
4118
+ const file = join10(nekoDir, SERVER_ID_FILENAME);
3410
4119
  try {
3411
4120
  const existing = (await readFile5(file, "utf8")).trim();
3412
4121
  if (existing !== "")
3413
4122
  return existing;
3414
4123
  } catch {}
3415
- const created = randomUUID();
3416
- await mkdir2(nekoDir, { recursive: true, mode: 448 });
3417
- await writeFile2(file, `${created}
4124
+ const created = randomUUID2();
4125
+ await mkdir3(nekoDir, { recursive: true, mode: 448 });
4126
+ await writeFile3(file, `${created}
3418
4127
  `, { mode: 384 });
3419
4128
  return created;
3420
4129
  }