@klhapp/skillmux 1.3.2 → 1.3.4

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/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.4](https://github.com/klhq/skillmux/compare/v1.3.3...v1.3.4) (2026-08-02)
9
+
10
+
11
+ ### Fixed
12
+
13
+ * **schema:** align published contract with server and guard GBNF bounds ([#104](https://github.com/klhq/skillmux/issues/104)) ([eb33613](https://github.com/klhq/skillmux/commit/eb336136a77c96fe5b660532dfbe191134e55ed3))
14
+
15
+ ## [1.3.3](https://github.com/klhq/skillmux/compare/v1.3.2...v1.3.3) (2026-08-02)
16
+
17
+
18
+ ### Fixed
19
+
20
+ * **server:** remove maxLength from resolve_skill schema to avoid GBNF overflow ([2621e73](https://github.com/klhq/skillmux/commit/2621e73bdb671d03ba8f458b7c3ceb223e8859c4))
21
+
8
22
  ## [1.3.2](https://github.com/klhq/skillmux/compare/v1.3.1...v1.3.2) (2026-07-31)
9
23
 
10
24
 
package/docs/schema.json CHANGED
@@ -38,8 +38,7 @@
38
38
  "query": {
39
39
  "type": "string",
40
40
  "description": "Natural-language task description to route. Normalized (NFC) by the server; never semantically rewritten.",
41
- "minLength": 1,
42
- "maxLength": 8192
41
+ "minLength": 1
43
42
  }
44
43
  },
45
44
  "required": ["query"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klhapp/skillmux",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
4
4
  "description": "Skill management and retrieval for AI agents: sync native skills across clients and route the long tail over MCP",
5
5
  "type": "module",
6
6
  "private": false,
package/src/server.ts CHANGED
@@ -64,46 +64,7 @@ function safeTokenEquals(a: string, b: string): boolean {
64
64
  return timingSafeEqual(bufA, bufB);
65
65
  }
66
66
 
67
- export async function startServer(opts?: {
68
- transport?: "stdio" | "http";
69
- port?: number;
70
- config?: Config;
71
- clients?: Partial<Clients>;
72
- configPath?: string;
73
- }): Promise<ServerHandle> {
74
- const configPath = resolveConfigPath(opts?.configPath);
75
- const config = opts?.config ?? (await loadConfig(configPath));
76
- const initialClients = { ...createClients(config), ...opts?.clients };
77
- const snapshots = RuntimeSnapshotManager.create(config, initialClients);
78
- const inactiveReloadStatus: ReloadStatus = {
79
- last_successful_reload_at: null,
80
- last_reload_error: null,
81
- restart_required_keys: [],
82
- };
83
- configure({ config, clients: initialClients });
84
- // An injected config has no guaranteed file source. Watch it only when the
85
- // caller explicitly supplies that source; normal server startup always watches.
86
- const watcherPath =
87
- opts?.configPath ?? (opts?.config ? undefined : configPath);
88
- const configWatcher = watcherPath
89
- ? await ConfigWatcher.start(watcherPath, {
90
- onReload: (nextConfig) => {
91
- const nextClients = {
92
- ...createClients(nextConfig),
93
- ...opts?.clients,
94
- };
95
- snapshots.replace(nextConfig, nextClients);
96
- configure({ config: nextConfig, clients: nextClients });
97
- },
98
- onError: (error) =>
99
- console.error("skillmux config reload error:", error),
100
- })
101
- : undefined;
102
- const stopWatcher = await startVaultWatcher();
103
- const initPromise = initializeRuntime(readinessState)
104
- .then(() => metricsRegistry.setReadiness(readinessState.get()))
105
- .catch((err) => console.error("skillmux runtime init error:", err));
106
-
67
+ export function createMcpServer(): McpServer {
107
68
  const server = new McpServer({ name: "skillmux", version: "0.1.0" });
108
69
 
109
70
  // Transport rule from schema.json: the SKILL.md body appears exactly once on
@@ -115,7 +76,7 @@ export async function startServer(opts?: {
115
76
  "Route a natural-language task description to the most relevant skill in the vault. " +
116
77
  "Returns outcome matched (skill delivered inline), ambiguous (shortlist — pick one, then call fetch_skill), " +
117
78
  "or no_match (proceed under your normal workflow).",
118
- inputSchema: { query: z.string().min(1).max(8192) },
79
+ inputSchema: { query: z.string().min(1) },
119
80
  },
120
81
  async ({ query }) => {
121
82
  const startTime = performance.now();
@@ -166,6 +127,51 @@ export async function startServer(opts?: {
166
127
  },
167
128
  );
168
129
 
130
+ return server;
131
+ }
132
+
133
+ export async function startServer(opts?: {
134
+ transport?: "stdio" | "http";
135
+ port?: number;
136
+ config?: Config;
137
+ clients?: Partial<Clients>;
138
+ configPath?: string;
139
+ }): Promise<ServerHandle> {
140
+ const configPath = resolveConfigPath(opts?.configPath);
141
+ const config = opts?.config ?? (await loadConfig(configPath));
142
+ const initialClients = { ...createClients(config), ...opts?.clients };
143
+ const snapshots = RuntimeSnapshotManager.create(config, initialClients);
144
+ const inactiveReloadStatus: ReloadStatus = {
145
+ last_successful_reload_at: null,
146
+ last_reload_error: null,
147
+ restart_required_keys: [],
148
+ };
149
+ configure({ config, clients: initialClients });
150
+ // An injected config has no guaranteed file source. Watch it only when the
151
+ // caller explicitly supplies that source; normal server startup always watches.
152
+ const watcherPath =
153
+ opts?.configPath ?? (opts?.config ? undefined : configPath);
154
+ const configWatcher = watcherPath
155
+ ? await ConfigWatcher.start(watcherPath, {
156
+ onReload: (nextConfig) => {
157
+ const nextClients = {
158
+ ...createClients(nextConfig),
159
+ ...opts?.clients,
160
+ };
161
+ snapshots.replace(nextConfig, nextClients);
162
+ configure({ config: nextConfig, clients: nextClients });
163
+ },
164
+ onError: (error) =>
165
+ console.error("skillmux config reload error:", error),
166
+ })
167
+ : undefined;
168
+ const stopWatcher = await startVaultWatcher();
169
+ const initPromise = initializeRuntime(readinessState)
170
+ .then(() => metricsRegistry.setReadiness(readinessState.get()))
171
+ .catch((err) => console.error("skillmux runtime init error:", err));
172
+
173
+ const server = createMcpServer();
174
+
169
175
  const transportType = opts?.transport ?? "stdio";
170
176
  if (transportType === "http") {
171
177
  const { WebStandardStreamableHTTPServerTransport } =