@nextclaw/server 0.5.29 → 0.6.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.
package/dist/index.d.ts CHANGED
@@ -55,7 +55,8 @@ type AgentProfileView = {
55
55
  default?: boolean;
56
56
  workspace?: string;
57
57
  model?: string;
58
- maxTokens?: number;
58
+ engine?: string;
59
+ engineConfig?: Record<string, unknown>;
59
60
  contextTokens?: number;
60
61
  maxToolIterations?: number;
61
62
  };
@@ -172,6 +173,8 @@ type RuntimeConfigUpdate = {
172
173
  agents?: {
173
174
  defaults?: {
174
175
  contextTokens?: number;
176
+ engine?: string;
177
+ engineConfig?: Record<string, unknown>;
175
178
  };
176
179
  list?: AgentProfileView[];
177
180
  };
@@ -229,6 +232,7 @@ type ChatTurnRequest = {
229
232
  chatId?: string;
230
233
  model?: string;
231
234
  metadata?: Record<string, unknown>;
235
+ runId?: string;
232
236
  };
233
237
  type ChatTurnResult = {
234
238
  reply: string;
@@ -259,16 +263,34 @@ type ChatTurnView = {
259
263
  completedAt: string;
260
264
  durationMs: number;
261
265
  };
266
+ type ChatCapabilitiesView = {
267
+ stopSupported: boolean;
268
+ stopReason?: string;
269
+ };
270
+ type ChatTurnStopRequest = {
271
+ runId: string;
272
+ sessionKey?: string;
273
+ agentId?: string;
274
+ };
275
+ type ChatTurnStopResult = {
276
+ stopped: boolean;
277
+ runId: string;
278
+ sessionKey?: string;
279
+ reason?: string;
280
+ };
262
281
  type UiChatRuntime = {
263
282
  processTurn: (params: ChatTurnRequest) => Promise<ChatTurnResult>;
264
283
  processTurnStream?: (params: ChatTurnRequest) => AsyncGenerator<ChatTurnStreamEvent>;
284
+ getCapabilities?: (params: Pick<ChatTurnRequest, "sessionKey" | "agentId">) => Promise<ChatCapabilitiesView> | ChatCapabilitiesView;
285
+ stopTurn?: (params: ChatTurnStopRequest) => Promise<ChatTurnStopResult> | ChatTurnStopResult;
265
286
  };
266
287
  type ConfigView = {
267
288
  agents: {
268
289
  defaults: {
269
290
  model: string;
270
291
  workspace?: string;
271
- maxTokens?: number;
292
+ engine?: string;
293
+ engineConfig?: Record<string, unknown>;
272
294
  contextTokens?: number;
273
295
  maxToolIterations?: number;
274
296
  };
@@ -463,6 +485,8 @@ type MarketplaceInstalledRecord = {
463
485
  id?: string;
464
486
  spec: string;
465
487
  label?: string;
488
+ description?: string;
489
+ descriptionZh?: string;
466
490
  source?: string;
467
491
  installedAt?: string;
468
492
  enabled?: boolean;
@@ -631,7 +655,6 @@ declare function executeConfigAction(configPath: string, actionId: string, reque
631
655
  declare function loadConfigOrDefault(configPath: string): Config;
632
656
  declare function updateModel(configPath: string, patch: {
633
657
  model?: string;
634
- maxTokens?: number;
635
658
  }): ConfigView;
636
659
  declare function updateProvider(configPath: string, providerName: string, patch: ProviderConfigUpdate): ProviderConfigView | null;
637
660
  declare function createCustomProvider(configPath: string, patch?: ProviderConfigUpdate): {
@@ -652,4 +675,4 @@ declare function deleteSession(configPath: string, key: string): boolean;
652
675
  declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "agents" | "bindings" | "session">;
653
676
  declare function updateSecrets(configPath: string, patch: SecretsConfigUpdate): SecretsView;
654
677
 
655
- export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, type ChatTurnRequest, type ChatTurnResult, type ChatTurnStreamEvent, type ChatTurnView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type CronActionResult, type CronEnableRequest, type CronJobStateView, type CronJobView, type CronListView, type CronPayloadView, type CronRunRequest, type CronScheduleView, type MarketplaceApiConfig, type MarketplaceInstallKind, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplaceLocalizedTextMap, type MarketplacePluginContentView, type MarketplacePluginInstallRequest, type MarketplacePluginInstallResult, type MarketplacePluginManageAction, type MarketplacePluginManageRequest, type MarketplacePluginManageResult, type MarketplaceRecommendationView, type MarketplaceSkillContentView, type MarketplaceSkillInstallRequest, type MarketplaceSkillInstallResult, type MarketplaceSkillManageAction, type MarketplaceSkillManageRequest, type MarketplaceSkillManageResult, type MarketplaceSort, type ProviderConfigUpdate, type ProviderConfigView, type ProviderConnectionTestRequest, type ProviderConnectionTestResult, type ProviderCreateRequest, type ProviderCreateResult, type ProviderDeleteResult, type ProviderSpecView, type RuntimeConfigUpdate, type SecretProviderEnvView, type SecretProviderExecView, type SecretProviderFileView, type SecretProviderView, type SecretRefView, type SecretSourceView, type SecretsConfigUpdate, type SecretsView, type SessionConfigView, type SessionEntryView, type SessionEventView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiChatRuntime, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSecrets };
678
+ export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, type ChatCapabilitiesView, type ChatTurnRequest, type ChatTurnResult, type ChatTurnStopRequest, type ChatTurnStopResult, type ChatTurnStreamEvent, type ChatTurnView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type CronActionResult, type CronEnableRequest, type CronJobStateView, type CronJobView, type CronListView, type CronPayloadView, type CronRunRequest, type CronScheduleView, type MarketplaceApiConfig, type MarketplaceInstallKind, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplaceLocalizedTextMap, type MarketplacePluginContentView, type MarketplacePluginInstallRequest, type MarketplacePluginInstallResult, type MarketplacePluginManageAction, type MarketplacePluginManageRequest, type MarketplacePluginManageResult, type MarketplaceRecommendationView, type MarketplaceSkillContentView, type MarketplaceSkillInstallRequest, type MarketplaceSkillInstallResult, type MarketplaceSkillManageAction, type MarketplaceSkillManageRequest, type MarketplaceSkillManageResult, type MarketplaceSort, type ProviderConfigUpdate, type ProviderConfigView, type ProviderConnectionTestRequest, type ProviderConnectionTestResult, type ProviderCreateRequest, type ProviderCreateResult, type ProviderDeleteResult, type ProviderSpecView, type RuntimeConfigUpdate, type SecretProviderEnvView, type SecretProviderExecView, type SecretProviderFileView, type SecretProviderView, type SecretRefView, type SecretSourceView, type SecretsConfigUpdate, type SecretsView, type SessionConfigView, type SessionEntryView, type SessionEventView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiChatRuntime, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSecrets };
package/dist/index.js CHANGED
@@ -519,9 +519,6 @@ function updateModel(configPath, patch) {
519
519
  if (typeof patch.model === "string") {
520
520
  config.agents.defaults.model = patch.model;
521
521
  }
522
- if (typeof patch.maxTokens === "number" && Number.isFinite(patch.maxTokens)) {
523
- config.agents.defaults.maxTokens = Math.max(1, Math.trunc(patch.maxTokens));
524
- }
525
522
  const next = ConfigSchema.parse(config);
526
523
  saveConfig(next, configPath);
527
524
  return buildConfigView(next);
@@ -917,17 +914,33 @@ function deleteSession(configPath, key) {
917
914
  }
918
915
  function updateRuntime(configPath, patch) {
919
916
  const config = loadConfigOrDefault(configPath);
920
- if (patch.agents?.defaults && Object.prototype.hasOwnProperty.call(patch.agents.defaults, "contextTokens")) {
921
- const nextContextTokens = patch.agents.defaults.contextTokens;
917
+ const defaultsPatch = patch.agents?.defaults;
918
+ if (defaultsPatch && Object.prototype.hasOwnProperty.call(defaultsPatch, "contextTokens")) {
919
+ const nextContextTokens = defaultsPatch.contextTokens;
922
920
  if (typeof nextContextTokens === "number" && Number.isFinite(nextContextTokens)) {
923
921
  config.agents.defaults.contextTokens = Math.max(1e3, Math.trunc(nextContextTokens));
924
922
  }
925
923
  }
924
+ if (defaultsPatch && Object.prototype.hasOwnProperty.call(defaultsPatch, "engine")) {
925
+ config.agents.defaults.engine = normalizeOptionalString(defaultsPatch.engine) ?? "native";
926
+ }
927
+ if (defaultsPatch && Object.prototype.hasOwnProperty.call(defaultsPatch, "engineConfig")) {
928
+ const nextEngineConfig = defaultsPatch.engineConfig;
929
+ if (nextEngineConfig && typeof nextEngineConfig === "object" && !Array.isArray(nextEngineConfig)) {
930
+ config.agents.defaults.engineConfig = { ...nextEngineConfig };
931
+ }
932
+ }
926
933
  if (patch.agents && Object.prototype.hasOwnProperty.call(patch.agents, "list")) {
927
- config.agents.list = (patch.agents.list ?? []).map((entry) => ({
928
- ...entry,
929
- default: Boolean(entry.default)
930
- }));
934
+ config.agents.list = (patch.agents.list ?? []).map((entry) => {
935
+ const normalizedEngine = normalizeOptionalString(entry.engine);
936
+ const hasEngineConfig = entry.engineConfig && typeof entry.engineConfig === "object" && !Array.isArray(entry.engineConfig);
937
+ return {
938
+ ...entry,
939
+ default: Boolean(entry.default),
940
+ ...normalizedEngine ? { engine: normalizedEngine } : {},
941
+ ...hasEngineConfig ? { engineConfig: { ...entry.engineConfig } } : {}
942
+ };
943
+ });
931
944
  }
932
945
  if (Object.prototype.hasOwnProperty.call(patch, "bindings")) {
933
946
  config.bindings = patch.bindings ?? [];
@@ -1175,6 +1188,11 @@ function resolveAgentIdFromSessionKey(sessionKey) {
1175
1188
  const agentId = readNonEmptyString(parsed?.agentId);
1176
1189
  return agentId;
1177
1190
  }
1191
+ function createChatRunId() {
1192
+ const now = Date.now().toString(36);
1193
+ const rand = Math.random().toString(36).slice(2, 10);
1194
+ return `run-${now}-${rand}`;
1195
+ }
1178
1196
  function buildChatTurnView(params) {
1179
1197
  const completedAt = /* @__PURE__ */ new Date();
1180
1198
  return {
@@ -1364,11 +1382,16 @@ function collectInstalledSkillRecords(options) {
1364
1382
  const listedSkills = skillsLoader?.listSkills(false) ?? [];
1365
1383
  const records = listedSkills.map((skill) => {
1366
1384
  const enabled = availableSkillSet.has(skill.name);
1385
+ const metadata = skillsLoader?.getSkillMetadata?.(skill.name);
1386
+ const description = readNonEmptyString(metadata?.description);
1387
+ const descriptionZh = readNonEmptyString(metadata?.description_zh) ?? readNonEmptyString(metadata?.descriptionZh) ?? readNonEmptyString(MARKETPLACE_ZH_COPY_BY_SLUG[skill.name]?.description);
1367
1388
  return {
1368
1389
  type: "skill",
1369
1390
  id: skill.name,
1370
1391
  spec: skill.name,
1371
1392
  label: skill.name,
1393
+ ...description ? { description } : {},
1394
+ ...descriptionZh ? { descriptionZh } : {},
1372
1395
  source: skill.source,
1373
1396
  enabled,
1374
1397
  runtimeStatus: enabled ? "enabled" : "disabled"
@@ -2248,23 +2271,17 @@ function createUiRouter(options) {
2248
2271
  return c.json(err("INVALID_BODY", "invalid json body"), 400);
2249
2272
  }
2250
2273
  const hasModel = typeof body.data.model === "string";
2251
- const hasMaxTokens = typeof body.data.maxTokens === "number";
2252
- if (!hasModel && !hasMaxTokens) {
2253
- return c.json(err("INVALID_BODY", "model or maxTokens is required"), 400);
2274
+ if (!hasModel) {
2275
+ return c.json(err("INVALID_BODY", "model is required"), 400);
2254
2276
  }
2255
2277
  const view = updateModel(options.configPath, {
2256
- model: hasModel ? body.data.model : void 0,
2257
- maxTokens: hasMaxTokens ? body.data.maxTokens : void 0
2278
+ model: body.data.model
2258
2279
  });
2259
2280
  if (hasModel) {
2260
2281
  options.publish({ type: "config.updated", payload: { path: "agents.defaults.model" } });
2261
2282
  }
2262
- if (hasMaxTokens) {
2263
- options.publish({ type: "config.updated", payload: { path: "agents.defaults.maxTokens" } });
2264
- }
2265
2283
  return c.json(ok({
2266
- model: view.agents.defaults.model,
2267
- maxTokens: view.agents.defaults.maxTokens
2284
+ model: view.agents.defaults.model
2268
2285
  }));
2269
2286
  });
2270
2287
  app.put("/api/config/providers/:provider", async (c) => {
@@ -2345,6 +2362,23 @@ function createUiRouter(options) {
2345
2362
  options.publish({ type: "config.updated", payload: { path: "secrets" } });
2346
2363
  return c.json(ok(result));
2347
2364
  });
2365
+ app.get("/api/chat/capabilities", async (c) => {
2366
+ const chatRuntime = options.chatRuntime;
2367
+ if (!chatRuntime) {
2368
+ return c.json(err("NOT_AVAILABLE", "chat runtime unavailable"), 503);
2369
+ }
2370
+ const query = c.req.query();
2371
+ const params = {
2372
+ sessionKey: readNonEmptyString(query.sessionKey),
2373
+ agentId: readNonEmptyString(query.agentId)
2374
+ };
2375
+ try {
2376
+ const capabilities = chatRuntime.getCapabilities ? await chatRuntime.getCapabilities(params) : { stopSupported: Boolean(chatRuntime.stopTurn) };
2377
+ return c.json(ok(capabilities));
2378
+ } catch (error) {
2379
+ return c.json(err("CHAT_RUNTIME_FAILED", String(error)), 500);
2380
+ }
2381
+ });
2348
2382
  app.post("/api/chat/turn", async (c) => {
2349
2383
  if (!options.chatRuntime) {
2350
2384
  return c.json(err("NOT_AVAILABLE", "chat runtime unavailable"), 503);
@@ -2388,6 +2422,31 @@ function createUiRouter(options) {
2388
2422
  return c.json(err("CHAT_TURN_FAILED", String(error)), 500);
2389
2423
  }
2390
2424
  });
2425
+ app.post("/api/chat/turn/stop", async (c) => {
2426
+ const chatRuntime = options.chatRuntime;
2427
+ if (!chatRuntime?.stopTurn) {
2428
+ return c.json(err("NOT_AVAILABLE", "chat turn stop is not supported by runtime"), 503);
2429
+ }
2430
+ const body = await readJson(c.req.raw);
2431
+ if (!body.ok || !body.data || typeof body.data !== "object") {
2432
+ return c.json(err("INVALID_BODY", "invalid json body"), 400);
2433
+ }
2434
+ const runId = readNonEmptyString(body.data.runId);
2435
+ if (!runId) {
2436
+ return c.json(err("INVALID_BODY", "runId is required"), 400);
2437
+ }
2438
+ const request = {
2439
+ runId,
2440
+ ...readNonEmptyString(body.data.sessionKey) ? { sessionKey: readNonEmptyString(body.data.sessionKey) } : {},
2441
+ ...readNonEmptyString(body.data.agentId) ? { agentId: readNonEmptyString(body.data.agentId) } : {}
2442
+ };
2443
+ try {
2444
+ const result = await chatRuntime.stopTurn(request);
2445
+ return c.json(ok(result));
2446
+ } catch (error) {
2447
+ return c.json(err("CHAT_TURN_STOP_FAILED", String(error)), 500);
2448
+ }
2449
+ });
2391
2450
  app.post("/api/chat/turn/stream", async (c) => {
2392
2451
  const chatRuntime = options.chatRuntime;
2393
2452
  if (!chatRuntime) {
@@ -2407,11 +2466,27 @@ function createUiRouter(options) {
2407
2466
  const metadata = isRecord(body.data.metadata) ? body.data.metadata : void 0;
2408
2467
  const requestedAgentId = readNonEmptyString(body.data.agentId) ?? resolveAgentIdFromSessionKey(sessionKey);
2409
2468
  const requestedModel = readNonEmptyString(body.data.model);
2469
+ const runId = createChatRunId();
2470
+ let stopCapabilities = { stopSupported: Boolean(chatRuntime.stopTurn) };
2471
+ if (chatRuntime.getCapabilities) {
2472
+ try {
2473
+ stopCapabilities = await chatRuntime.getCapabilities({
2474
+ sessionKey,
2475
+ ...requestedAgentId ? { agentId: requestedAgentId } : {}
2476
+ });
2477
+ } catch {
2478
+ stopCapabilities = {
2479
+ stopSupported: false,
2480
+ stopReason: "failed to resolve runtime stop capability"
2481
+ };
2482
+ }
2483
+ }
2410
2484
  const request = {
2411
2485
  message,
2412
2486
  sessionKey,
2413
2487
  channel: readNonEmptyString(body.data.channel) ?? "ui",
2414
2488
  chatId: readNonEmptyString(body.data.chatId) ?? "web-ui",
2489
+ runId,
2415
2490
  ...requestedAgentId ? { agentId: requestedAgentId } : {},
2416
2491
  ...requestedModel ? { model: requestedModel } : {},
2417
2492
  ...metadata ? { metadata } : {}
@@ -2425,7 +2500,10 @@ function createUiRouter(options) {
2425
2500
  try {
2426
2501
  push("ready", {
2427
2502
  sessionKey,
2428
- requestedAt: requestedAt.toISOString()
2503
+ requestedAt: requestedAt.toISOString(),
2504
+ runId,
2505
+ stopSupported: stopCapabilities.stopSupported,
2506
+ ...readNonEmptyString(stopCapabilities.stopReason) ? { stopReason: readNonEmptyString(stopCapabilities.stopReason) } : {}
2429
2507
  });
2430
2508
  const streamTurn = chatRuntime.processTurnStream;
2431
2509
  if (!streamTurn) {
@@ -2619,6 +2697,12 @@ function createUiRouter(options) {
2619
2697
  if (body.data.agents?.defaults && Object.prototype.hasOwnProperty.call(body.data.agents.defaults, "contextTokens")) {
2620
2698
  options.publish({ type: "config.updated", payload: { path: "agents.defaults.contextTokens" } });
2621
2699
  }
2700
+ if (body.data.agents?.defaults && Object.prototype.hasOwnProperty.call(body.data.agents.defaults, "engine")) {
2701
+ options.publish({ type: "config.updated", payload: { path: "agents.defaults.engine" } });
2702
+ }
2703
+ if (body.data.agents?.defaults && Object.prototype.hasOwnProperty.call(body.data.agents.defaults, "engineConfig")) {
2704
+ options.publish({ type: "config.updated", payload: { path: "agents.defaults.engineConfig" } });
2705
+ }
2622
2706
  options.publish({ type: "config.updated", payload: { path: "agents.list" } });
2623
2707
  options.publish({ type: "config.updated", payload: { path: "bindings" } });
2624
2708
  options.publish({ type: "config.updated", payload: { path: "session" } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/server",
3
- "version": "0.5.29",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "description": "Nextclaw UI/API server.",
6
6
  "type": "module",
@@ -15,10 +15,10 @@
15
15
  ],
16
16
  "dependencies": {
17
17
  "@hono/node-server": "^1.13.3",
18
- "@nextclaw/openclaw-compat": "^0.1.33",
18
+ "@nextclaw/openclaw-compat": "^0.2.0",
19
19
  "hono": "^4.6.2",
20
20
  "ws": "^8.18.0",
21
- "@nextclaw/core": "^0.6.44"
21
+ "@nextclaw/core": "^0.7.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^20.17.6",