@nextclaw/server 0.8.0 → 0.9.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 +4 -2
- package/dist/index.js +104 -27
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -228,6 +228,7 @@ type SessionHistoryView = {
|
|
|
228
228
|
type SessionPatchUpdate = {
|
|
229
229
|
label?: string | null;
|
|
230
230
|
preferredModel?: string | null;
|
|
231
|
+
preferredThinking?: ThinkingLevel | null;
|
|
231
232
|
sessionType?: string | null;
|
|
232
233
|
clearHistory?: boolean;
|
|
233
234
|
};
|
|
@@ -465,6 +466,7 @@ type UiNcpAgent = {
|
|
|
465
466
|
agentClientEndpoint: NcpAgentClientEndpoint;
|
|
466
467
|
streamProvider?: NcpHttpAgentStreamProvider;
|
|
467
468
|
sessionApi?: NcpSessionApi;
|
|
469
|
+
listSessionTypes?: () => Promise<ChatSessionTypesView> | ChatSessionTypesView;
|
|
468
470
|
basePath?: string;
|
|
469
471
|
};
|
|
470
472
|
type ConfigView = {
|
|
@@ -938,8 +940,8 @@ declare function testProviderConnection(configPath: string, providerName: string
|
|
|
938
940
|
declare function updateChannel(configPath: string, channelName: string, patch: Record<string, unknown>): Record<string, unknown> | null;
|
|
939
941
|
declare const DEFAULT_SESSION_TYPE = "native";
|
|
940
942
|
declare class SessionPatchValidationError extends Error {
|
|
941
|
-
readonly code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE";
|
|
942
|
-
constructor(code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE", message: string);
|
|
943
|
+
readonly code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE" | "PREFERRED_THINKING_INVALID";
|
|
944
|
+
constructor(code: "SESSION_TYPE_INVALID" | "SESSION_TYPE_IMMUTABLE" | "SESSION_TYPE_UNAVAILABLE" | "PREFERRED_THINKING_INVALID", message: string);
|
|
943
945
|
}
|
|
944
946
|
declare function listSessions(configPath: string, query?: {
|
|
945
947
|
q?: string;
|
package/dist/index.js
CHANGED
|
@@ -512,7 +512,7 @@ import {
|
|
|
512
512
|
SessionManager,
|
|
513
513
|
getWorkspacePathFromConfig,
|
|
514
514
|
normalizeThinkingLevels,
|
|
515
|
-
parseThinkingLevel
|
|
515
|
+
parseThinkingLevel as parseThinkingLevel2
|
|
516
516
|
} from "@nextclaw/core";
|
|
517
517
|
|
|
518
518
|
// src/ui/provider-overrides.ts
|
|
@@ -603,6 +603,42 @@ function findServerBuiltinProviderByName(name) {
|
|
|
603
603
|
return SERVER_BUILTIN_PROVIDER_OVERRIDE_MAP.get(name) ?? findBuiltinProviderByName(name);
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
+
// src/ui/session-preference-patch.ts
|
|
607
|
+
import { parseThinkingLevel } from "@nextclaw/core";
|
|
608
|
+
function applySessionPreferencePatch(params) {
|
|
609
|
+
const nextMetadata = params.metadata;
|
|
610
|
+
const { patch } = params;
|
|
611
|
+
if (Object.prototype.hasOwnProperty.call(patch, "label")) {
|
|
612
|
+
const label = typeof patch.label === "string" ? patch.label.trim() : "";
|
|
613
|
+
if (label) {
|
|
614
|
+
nextMetadata.label = label;
|
|
615
|
+
} else {
|
|
616
|
+
delete nextMetadata.label;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
if (Object.prototype.hasOwnProperty.call(patch, "preferredModel")) {
|
|
620
|
+
const preferredModel = typeof patch.preferredModel === "string" ? patch.preferredModel.trim() : "";
|
|
621
|
+
if (preferredModel) {
|
|
622
|
+
nextMetadata.preferred_model = preferredModel;
|
|
623
|
+
} else {
|
|
624
|
+
delete nextMetadata.preferred_model;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (Object.prototype.hasOwnProperty.call(patch, "preferredThinking")) {
|
|
628
|
+
const preferredThinking = typeof patch.preferredThinking === "string" ? patch.preferredThinking.trim() : "";
|
|
629
|
+
if (!preferredThinking) {
|
|
630
|
+
delete nextMetadata.preferred_thinking;
|
|
631
|
+
} else {
|
|
632
|
+
const normalizedThinking = parseThinkingLevel(preferredThinking);
|
|
633
|
+
if (!normalizedThinking) {
|
|
634
|
+
throw params.createInvalidThinkingError("preferredThinking must be a supported thinking level");
|
|
635
|
+
}
|
|
636
|
+
nextMetadata.preferred_thinking = normalizedThinking;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
return nextMetadata;
|
|
640
|
+
}
|
|
641
|
+
|
|
606
642
|
// src/ui/config.ts
|
|
607
643
|
var MASK_MIN_LENGTH = 8;
|
|
608
644
|
var EXTRA_SENSITIVE_PATH_PATTERNS = [/authorization/i, /cookie/i, /session/i, /bearer/i];
|
|
@@ -955,7 +991,7 @@ function normalizeModelThinkingConfig(input) {
|
|
|
955
991
|
if (supported.length === 0) {
|
|
956
992
|
continue;
|
|
957
993
|
}
|
|
958
|
-
const defaultLevel =
|
|
994
|
+
const defaultLevel = parseThinkingLevel2(rawValue.default);
|
|
959
995
|
if (defaultLevel && supported.includes(defaultLevel)) {
|
|
960
996
|
normalized[model] = { supported, default: defaultLevel };
|
|
961
997
|
} else {
|
|
@@ -1669,22 +1705,11 @@ function patchSession(configPath, key, patch, options) {
|
|
|
1669
1705
|
if (patch.clearHistory) {
|
|
1670
1706
|
sessionManager.clear(session);
|
|
1671
1707
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
delete session.metadata.label;
|
|
1678
|
-
}
|
|
1679
|
-
}
|
|
1680
|
-
if (Object.prototype.hasOwnProperty.call(patch, "preferredModel")) {
|
|
1681
|
-
const preferredModel = typeof patch.preferredModel === "string" ? patch.preferredModel.trim() : "";
|
|
1682
|
-
if (preferredModel) {
|
|
1683
|
-
session.metadata.preferred_model = preferredModel;
|
|
1684
|
-
} else {
|
|
1685
|
-
delete session.metadata.preferred_model;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1708
|
+
applySessionPreferencePatch({
|
|
1709
|
+
metadata: session.metadata,
|
|
1710
|
+
patch,
|
|
1711
|
+
createInvalidThinkingError: (message) => new SessionPatchValidationError("PREFERRED_THINKING_INVALID", message)
|
|
1712
|
+
});
|
|
1688
1713
|
if (Object.prototype.hasOwnProperty.call(patch, "sessionType")) {
|
|
1689
1714
|
const normalizedSessionType = normalizeSessionType(patch.sessionType);
|
|
1690
1715
|
if (!normalizedSessionType) {
|
|
@@ -1822,13 +1847,7 @@ function resolveSessionTypeLabel(sessionType) {
|
|
|
1822
1847
|
if (sessionType === "native") {
|
|
1823
1848
|
return "Native";
|
|
1824
1849
|
}
|
|
1825
|
-
|
|
1826
|
-
return "Codex";
|
|
1827
|
-
}
|
|
1828
|
-
if (sessionType === "claude-agent-sdk") {
|
|
1829
|
-
return "Claude Code";
|
|
1830
|
-
}
|
|
1831
|
-
return sessionType;
|
|
1850
|
+
return sessionType.trim().split(/[-_]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ") || sessionType;
|
|
1832
1851
|
}
|
|
1833
1852
|
async function buildChatSessionTypesView(chatRuntime) {
|
|
1834
1853
|
if (!chatRuntime?.listSessionTypes) {
|
|
@@ -3283,6 +3302,14 @@ var NcpSessionRoutesController = class {
|
|
|
3283
3302
|
constructor(options) {
|
|
3284
3303
|
this.options = options;
|
|
3285
3304
|
}
|
|
3305
|
+
getSessionTypes = async (c) => {
|
|
3306
|
+
const listSessionTypes = this.options.ncpAgent?.listSessionTypes;
|
|
3307
|
+
const payload = listSessionTypes ? await listSessionTypes() : {
|
|
3308
|
+
defaultType: "native",
|
|
3309
|
+
options: [{ value: "native", label: "Native" }]
|
|
3310
|
+
};
|
|
3311
|
+
return c.json(ok(payload));
|
|
3312
|
+
};
|
|
3286
3313
|
listSessions = async (c) => {
|
|
3287
3314
|
const sessionApi = this.options.ncpAgent?.sessionApi;
|
|
3288
3315
|
if (!sessionApi) {
|
|
@@ -3329,6 +3356,55 @@ var NcpSessionRoutesController = class {
|
|
|
3329
3356
|
};
|
|
3330
3357
|
return c.json(ok(payload));
|
|
3331
3358
|
};
|
|
3359
|
+
patchSession = async (c) => {
|
|
3360
|
+
const sessionApi = this.options.ncpAgent?.sessionApi;
|
|
3361
|
+
if (!sessionApi) {
|
|
3362
|
+
return c.json(err("NOT_AVAILABLE", "ncp session api unavailable"), 503);
|
|
3363
|
+
}
|
|
3364
|
+
const sessionId = decodeURIComponent(c.req.param("sessionId"));
|
|
3365
|
+
const body = await readJson(c.req.raw);
|
|
3366
|
+
if (!body.ok || !body.data || typeof body.data !== "object") {
|
|
3367
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
3368
|
+
}
|
|
3369
|
+
const patch = body.data;
|
|
3370
|
+
if (patch.clearHistory) {
|
|
3371
|
+
return c.json(err("UNSUPPORTED_PATCH", "clearHistory is not supported for ncp sessions"), 400);
|
|
3372
|
+
}
|
|
3373
|
+
const existing = await sessionApi.getSession(sessionId);
|
|
3374
|
+
if (!existing) {
|
|
3375
|
+
return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
|
|
3376
|
+
}
|
|
3377
|
+
const metadata = existing.metadata && typeof existing.metadata === "object" && !Array.isArray(existing.metadata) ? existing.metadata : {};
|
|
3378
|
+
let updated;
|
|
3379
|
+
try {
|
|
3380
|
+
const nextMetadata = applySessionPreferencePatch({
|
|
3381
|
+
metadata: structuredClone(metadata),
|
|
3382
|
+
patch,
|
|
3383
|
+
createInvalidThinkingError: () => new Error("PREFERRED_THINKING_INVALID")
|
|
3384
|
+
});
|
|
3385
|
+
if (Object.prototype.hasOwnProperty.call(patch, "sessionType")) {
|
|
3386
|
+
const sessionType = typeof patch.sessionType === "string" ? patch.sessionType.trim() : "";
|
|
3387
|
+
if (sessionType) {
|
|
3388
|
+
nextMetadata.session_type = sessionType;
|
|
3389
|
+
} else {
|
|
3390
|
+
delete nextMetadata.session_type;
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
updated = await sessionApi.updateSession(sessionId, {
|
|
3394
|
+
metadata: nextMetadata
|
|
3395
|
+
});
|
|
3396
|
+
} catch (error) {
|
|
3397
|
+
if (error instanceof Error && error.message === "PREFERRED_THINKING_INVALID") {
|
|
3398
|
+
return c.json(err("PREFERRED_THINKING_INVALID", "preferredThinking must be a supported thinking level"), 400);
|
|
3399
|
+
}
|
|
3400
|
+
throw error;
|
|
3401
|
+
}
|
|
3402
|
+
if (!updated) {
|
|
3403
|
+
return c.json(err("NOT_FOUND", `ncp session not found: ${sessionId}`), 404);
|
|
3404
|
+
}
|
|
3405
|
+
this.options.publish({ type: "config.updated", payload: { path: "session" } });
|
|
3406
|
+
return c.json(ok(updated));
|
|
3407
|
+
};
|
|
3332
3408
|
deleteSession = async (c) => {
|
|
3333
3409
|
const sessionApi = this.options.ncpAgent?.sessionApi;
|
|
3334
3410
|
if (!sessionApi) {
|
|
@@ -3348,7 +3424,6 @@ var NcpSessionRoutesController = class {
|
|
|
3348
3424
|
// src/ui/router/marketplace/constants.ts
|
|
3349
3425
|
var DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
|
|
3350
3426
|
var NEXTCLAW_PLUGIN_NPM_PREFIX = "@nextclaw/channel-plugin-";
|
|
3351
|
-
var CLAWBAY_CHANNEL_PLUGIN_NPM_SPEC = "@clawbay/clawbay-channel";
|
|
3352
3427
|
var BUILTIN_CHANNEL_PLUGIN_ID_PREFIX = "builtin-channel-";
|
|
3353
3428
|
var MARKETPLACE_REMOTE_PAGE_SIZE = 100;
|
|
3354
3429
|
var MARKETPLACE_REMOTE_MAX_PAGES = 20;
|
|
@@ -3662,7 +3737,7 @@ function normalizePluginNpmSpec(rawSpec) {
|
|
|
3662
3737
|
}
|
|
3663
3738
|
function isSupportedMarketplacePluginSpec(rawSpec) {
|
|
3664
3739
|
const spec = normalizePluginNpmSpec(rawSpec);
|
|
3665
|
-
return spec.
|
|
3740
|
+
return spec.length > 0;
|
|
3666
3741
|
}
|
|
3667
3742
|
function resolvePluginCanonicalSpec(params) {
|
|
3668
3743
|
const rawInstallSpec = typeof params.installSpec === "string" ? params.installSpec.trim() : "";
|
|
@@ -4602,8 +4677,10 @@ function createUiRouter(options) {
|
|
|
4602
4677
|
agentClientEndpoint: options.ncpAgent.agentClientEndpoint,
|
|
4603
4678
|
streamProvider: options.ncpAgent.streamProvider
|
|
4604
4679
|
});
|
|
4680
|
+
app.get("/api/ncp/session-types", ncpSessionController.getSessionTypes);
|
|
4605
4681
|
app.get("/api/ncp/sessions", ncpSessionController.listSessions);
|
|
4606
4682
|
app.get("/api/ncp/sessions/:sessionId", ncpSessionController.getSession);
|
|
4683
|
+
app.put("/api/ncp/sessions/:sessionId", ncpSessionController.patchSession);
|
|
4607
4684
|
app.get("/api/ncp/sessions/:sessionId/messages", ncpSessionController.listSessionMessages);
|
|
4608
4685
|
app.delete("/api/ncp/sessions/:sessionId", ncpSessionController.deleteSession);
|
|
4609
4686
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Nextclaw UI/API server.",
|
|
6
6
|
"type": "module",
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"hono": "^4.6.2",
|
|
20
20
|
"ws": "^8.18.0",
|
|
21
21
|
"@nextclaw/ncp-http-agent-server": "0.3.0",
|
|
22
|
-
"@nextclaw/openclaw-compat": "0.3.
|
|
23
|
-
"@nextclaw/ncp": "0.3.0",
|
|
22
|
+
"@nextclaw/openclaw-compat": "0.3.1",
|
|
24
23
|
"@nextclaw/runtime": "0.2.0",
|
|
25
|
-
"@nextclaw/core": "0.9.0"
|
|
24
|
+
"@nextclaw/core": "0.9.0",
|
|
25
|
+
"@nextclaw/ncp": "0.3.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^20.17.6",
|