@nextclaw/server 0.12.1 → 0.12.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/index.d.ts +47 -3
- package/dist/index.js +335 -78
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -372,6 +372,7 @@ type UiRemoteAccessHost = {
|
|
|
372
372
|
startBrowserAuth: (input: RemoteBrowserAuthStartRequest) => Promise<RemoteBrowserAuthStartResult>;
|
|
373
373
|
pollBrowserAuth: (input: RemoteBrowserAuthPollRequest) => Promise<RemoteBrowserAuthPollResult>;
|
|
374
374
|
logout: () => Promise<RemoteAccessView> | RemoteAccessView;
|
|
375
|
+
updateProfile: (input: RemoteAccountProfileUpdateRequest) => Promise<RemoteAccessView> | RemoteAccessView;
|
|
375
376
|
updateSettings: (input: RemoteSettingsUpdateRequest) => Promise<RemoteAccessView> | RemoteAccessView;
|
|
376
377
|
runDoctor: () => Promise<RemoteDoctorView>;
|
|
377
378
|
controlService: (action: RemoteServiceAction) => Promise<RemoteServiceActionResult>;
|
|
@@ -486,8 +487,9 @@ type ProviderConnectionTestResult = {
|
|
|
486
487
|
latencyMs: number;
|
|
487
488
|
message: string;
|
|
488
489
|
};
|
|
489
|
-
type SearchProviderName = "bocha" | "brave";
|
|
490
|
+
type SearchProviderName = "bocha" | "tavily" | "brave";
|
|
490
491
|
type BochaFreshnessValue = "noLimit" | "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | string;
|
|
492
|
+
type TavilySearchDepthValue = "basic" | "advanced";
|
|
491
493
|
type SearchProviderConfigView = {
|
|
492
494
|
enabled: boolean;
|
|
493
495
|
apiKeySet: boolean;
|
|
@@ -496,6 +498,8 @@ type SearchProviderConfigView = {
|
|
|
496
498
|
docsUrl?: string;
|
|
497
499
|
summary?: boolean;
|
|
498
500
|
freshness?: BochaFreshnessValue;
|
|
501
|
+
searchDepth?: TavilySearchDepthValue;
|
|
502
|
+
includeAnswer?: boolean;
|
|
499
503
|
};
|
|
500
504
|
type SearchConfigView = {
|
|
501
505
|
provider: SearchProviderName;
|
|
@@ -505,6 +509,7 @@ type SearchConfigView = {
|
|
|
505
509
|
};
|
|
506
510
|
providers: {
|
|
507
511
|
bocha: SearchProviderConfigView;
|
|
512
|
+
tavily: SearchProviderConfigView;
|
|
508
513
|
brave: SearchProviderConfigView;
|
|
509
514
|
};
|
|
510
515
|
};
|
|
@@ -522,6 +527,12 @@ type SearchConfigUpdate = {
|
|
|
522
527
|
summary?: boolean;
|
|
523
528
|
freshness?: BochaFreshnessValue | null;
|
|
524
529
|
};
|
|
530
|
+
tavily?: {
|
|
531
|
+
apiKey?: string | null;
|
|
532
|
+
baseUrl?: string | null;
|
|
533
|
+
searchDepth?: TavilySearchDepthValue | null;
|
|
534
|
+
includeAnswer?: boolean;
|
|
535
|
+
};
|
|
525
536
|
brave?: {
|
|
526
537
|
apiKey?: string | null;
|
|
527
538
|
baseUrl?: string | null;
|
|
@@ -605,10 +616,14 @@ type AuthEnabledUpdateRequest = {
|
|
|
605
616
|
type RemoteAccountView = {
|
|
606
617
|
loggedIn: boolean;
|
|
607
618
|
email?: string;
|
|
619
|
+
username?: string | null;
|
|
608
620
|
role?: string;
|
|
609
621
|
platformBase?: string | null;
|
|
610
622
|
apiBase?: string | null;
|
|
611
623
|
};
|
|
624
|
+
type RemoteAccountProfileUpdateRequest = {
|
|
625
|
+
username: string;
|
|
626
|
+
};
|
|
612
627
|
type RemoteRuntimeView = {
|
|
613
628
|
enabled: boolean;
|
|
614
629
|
mode: "service" | "foreground";
|
|
@@ -700,6 +715,8 @@ type AgentProfileView = {
|
|
|
700
715
|
avatarUrl?: string;
|
|
701
716
|
workspace?: string;
|
|
702
717
|
model?: string;
|
|
718
|
+
runtime?: string;
|
|
719
|
+
runtimeConfig?: Record<string, unknown>;
|
|
703
720
|
engine?: string;
|
|
704
721
|
engineConfig?: Record<string, unknown>;
|
|
705
722
|
contextTokens?: number;
|
|
@@ -712,6 +729,17 @@ type AgentCreateRequest = {
|
|
|
712
729
|
description?: string;
|
|
713
730
|
avatar?: string;
|
|
714
731
|
home?: string;
|
|
732
|
+
model?: string;
|
|
733
|
+
runtime?: string;
|
|
734
|
+
runtimeConfig?: Record<string, unknown>;
|
|
735
|
+
};
|
|
736
|
+
type AgentUpdateRequest = {
|
|
737
|
+
displayName?: string;
|
|
738
|
+
description?: string;
|
|
739
|
+
avatar?: string;
|
|
740
|
+
model?: string;
|
|
741
|
+
runtime?: string;
|
|
742
|
+
runtimeConfig?: Record<string, unknown>;
|
|
715
743
|
};
|
|
716
744
|
type AgentDeleteResult = {
|
|
717
745
|
deleted: boolean;
|
|
@@ -854,6 +882,20 @@ type CronListView = {
|
|
|
854
882
|
jobs: CronJobView[];
|
|
855
883
|
total: number;
|
|
856
884
|
};
|
|
885
|
+
type CronCreateRequest = {
|
|
886
|
+
name: string;
|
|
887
|
+
message: string;
|
|
888
|
+
schedule: CronScheduleView;
|
|
889
|
+
agentId?: string | null;
|
|
890
|
+
deliver?: boolean;
|
|
891
|
+
channel?: string | null;
|
|
892
|
+
to?: string | null;
|
|
893
|
+
accountId?: string | null;
|
|
894
|
+
deleteAfterRun?: boolean;
|
|
895
|
+
};
|
|
896
|
+
type CronCreateResult = {
|
|
897
|
+
job: CronJobView;
|
|
898
|
+
};
|
|
857
899
|
type CronEnableRequest = {
|
|
858
900
|
enabled: boolean;
|
|
859
901
|
};
|
|
@@ -1192,6 +1234,9 @@ type PluginConfigProjectionOptions = {
|
|
|
1192
1234
|
pluginUiMetadata?: PluginUiMetadata[];
|
|
1193
1235
|
};
|
|
1194
1236
|
//#endregion
|
|
1237
|
+
//#region src/ui/search-config.d.ts
|
|
1238
|
+
declare function updateSearch(configPath: string, patch: SearchConfigUpdate): ConfigView["search"];
|
|
1239
|
+
//#endregion
|
|
1195
1240
|
//#region src/ui/config.d.ts
|
|
1196
1241
|
type ExecuteActionResult = {
|
|
1197
1242
|
ok: true;
|
|
@@ -1211,7 +1256,6 @@ declare function updateModel(configPath: string, patch: {
|
|
|
1211
1256
|
model?: string;
|
|
1212
1257
|
workspace?: string;
|
|
1213
1258
|
}): ConfigView;
|
|
1214
|
-
declare function updateSearch(configPath: string, patch: SearchConfigUpdate): ConfigView["search"];
|
|
1215
1259
|
declare function updateProvider(configPath: string, providerName: string, patch: ProviderConfigUpdate): ProviderConfigView | null;
|
|
1216
1260
|
declare function createCustomProvider(configPath: string, patch?: ProviderConfigUpdate): {
|
|
1217
1261
|
name: string;
|
|
@@ -1243,4 +1287,4 @@ declare function getUiBridgeSecretPath(): string;
|
|
|
1243
1287
|
declare function readUiBridgeSecret(): string | null;
|
|
1244
1288
|
declare function ensureUiBridgeSecret(): string;
|
|
1245
1289
|
//#endregion
|
|
1246
|
-
export { AgentBindingView, AgentCreateRequest, AgentDeleteResult, AgentProfileView, ApiError, ApiResponse, AppMetaView, AuthEnabledUpdateRequest, AuthLoginRequest, AuthPasswordUpdateRequest, AuthSetupRequest, AuthStatusView, BindingPeerView, BochaFreshnessValue, BootstrapPhase, BootstrapRemoteState, BootstrapStageState, BootstrapStatusView, ChannelAuthPollRequest, ChannelAuthPollResult, ChannelAuthStartRequest, ChannelAuthStartResult, ChannelSpecView, type ChatSessionTypeCtaView, type ChatSessionTypeOptionView, type ChatSessionTypesView, ConfigActionExecuteRequest, ConfigActionExecuteResult, ConfigActionManifest, ConfigActionType, ConfigMetaView, ConfigSchemaResponse, ConfigUiHint, ConfigUiHints, ConfigView, CronActionResult, CronEnableRequest, CronJobStateView, CronJobView, CronListView, CronPayloadView, CronRunRequest, CronScheduleView, DEFAULT_SESSION_TYPE, MarketplaceApiConfig, MarketplaceInstallKind, MarketplaceInstallSkillParams, MarketplaceInstallSpec, MarketplaceInstalledRecord, MarketplaceInstalledView, MarketplaceInstaller, MarketplaceItemSummary, MarketplaceItemType, MarketplaceItemView, MarketplaceListView, MarketplaceLocalizedTextMap, MarketplaceMcpContentView, MarketplaceMcpDoctorResult, MarketplaceMcpInstallKind, MarketplaceMcpInstallRequest, MarketplaceMcpInstallResult, MarketplaceMcpInstallSpec, MarketplaceMcpManageAction, MarketplaceMcpManageRequest, MarketplaceMcpManageResult, MarketplaceMcpTemplateInput, MarketplacePluginContentView, MarketplacePluginInstallKind, MarketplacePluginInstallRequest, MarketplacePluginInstallResult, MarketplacePluginManageAction, MarketplacePluginManageRequest, MarketplacePluginManageResult, MarketplaceRecommendationView, MarketplaceSkillContentView, MarketplaceSkillInstallKind, MarketplaceSkillInstallRequest, MarketplaceSkillInstallResult, MarketplaceSkillManageAction, MarketplaceSkillManageRequest, MarketplaceSkillManageResult, MarketplaceSort, NcpSessionSkillsView, ProviderAuthImportResult, ProviderAuthPollRequest, ProviderAuthPollResult, ProviderAuthStartRequest, ProviderAuthStartResult, ProviderConfigUpdate, ProviderConfigView, ProviderConnectionTestRequest, ProviderConnectionTestResult, ProviderCreateRequest, ProviderCreateResult, ProviderDeleteResult, ProviderSpecView, RemoteAccessView, RemoteAccountView, RemoteBrowserAuthPollRequest, RemoteBrowserAuthPollResult, RemoteBrowserAuthStartRequest, RemoteBrowserAuthStartResult, RemoteDoctorCheckView, RemoteDoctorView, RemoteLoginRequest, RemoteRuntimeView, RemoteServiceAction, RemoteServiceActionResult, RemoteServiceView, RemoteSettingsUpdateRequest, RemoteSettingsView, RuntimeConfigUpdate, SearchConfigUpdate, SearchConfigView, SearchProviderConfigView, SearchProviderName, SearchProviderSpecView, SecretProviderEnvView, SecretProviderExecView, SecretProviderFileView, SecretProviderView, SecretRefView, SecretSourceView, SecretsConfigUpdate, SecretsView, ServerPathBreadcrumbView, ServerPathBrowseView, ServerPathEntryView, SessionConfigView, SessionEntryView, SessionEventView, SessionHistoryView, SessionMessageView, SessionPatchUpdate, SessionPatchValidationError, SessionSkillEntryView, SessionTypeDescribeParams, SessionsListView, UiNcpAgent, UiNcpAssetPutView, UiNcpAssetView, UiNcpSessionListView, UiNcpSessionMessagesView, UiNcpSessionService, UiNcpStoredAssetRecord, type UiRemoteAccessHost, UiServerEvent, UiServerHandle, UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, deleteSession, ensureUiBridgeSecret, executeConfigAction, getSessionHistory, getUiBridgeSecretPath, listSessions, loadConfigOrDefault, patchSession, readUiBridgeSecret, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
|
|
1290
|
+
export { AgentBindingView, AgentCreateRequest, AgentDeleteResult, AgentProfileView, AgentUpdateRequest, ApiError, ApiResponse, AppMetaView, AuthEnabledUpdateRequest, AuthLoginRequest, AuthPasswordUpdateRequest, AuthSetupRequest, AuthStatusView, BindingPeerView, BochaFreshnessValue, BootstrapPhase, BootstrapRemoteState, BootstrapStageState, BootstrapStatusView, ChannelAuthPollRequest, ChannelAuthPollResult, ChannelAuthStartRequest, ChannelAuthStartResult, ChannelSpecView, type ChatSessionTypeCtaView, type ChatSessionTypeOptionView, type ChatSessionTypesView, ConfigActionExecuteRequest, ConfigActionExecuteResult, ConfigActionManifest, ConfigActionType, ConfigMetaView, ConfigSchemaResponse, ConfigUiHint, ConfigUiHints, ConfigView, CronActionResult, CronCreateRequest, CronCreateResult, CronEnableRequest, CronJobStateView, CronJobView, CronListView, CronPayloadView, CronRunRequest, CronScheduleView, DEFAULT_SESSION_TYPE, MarketplaceApiConfig, MarketplaceInstallKind, MarketplaceInstallSkillParams, MarketplaceInstallSpec, MarketplaceInstalledRecord, MarketplaceInstalledView, MarketplaceInstaller, MarketplaceItemSummary, MarketplaceItemType, MarketplaceItemView, MarketplaceListView, MarketplaceLocalizedTextMap, MarketplaceMcpContentView, MarketplaceMcpDoctorResult, MarketplaceMcpInstallKind, MarketplaceMcpInstallRequest, MarketplaceMcpInstallResult, MarketplaceMcpInstallSpec, MarketplaceMcpManageAction, MarketplaceMcpManageRequest, MarketplaceMcpManageResult, MarketplaceMcpTemplateInput, MarketplacePluginContentView, MarketplacePluginInstallKind, MarketplacePluginInstallRequest, MarketplacePluginInstallResult, MarketplacePluginManageAction, MarketplacePluginManageRequest, MarketplacePluginManageResult, MarketplaceRecommendationView, MarketplaceSkillContentView, MarketplaceSkillInstallKind, MarketplaceSkillInstallRequest, MarketplaceSkillInstallResult, MarketplaceSkillManageAction, MarketplaceSkillManageRequest, MarketplaceSkillManageResult, MarketplaceSort, NcpSessionSkillsView, ProviderAuthImportResult, ProviderAuthPollRequest, ProviderAuthPollResult, ProviderAuthStartRequest, ProviderAuthStartResult, ProviderConfigUpdate, ProviderConfigView, ProviderConnectionTestRequest, ProviderConnectionTestResult, ProviderCreateRequest, ProviderCreateResult, ProviderDeleteResult, ProviderSpecView, RemoteAccessView, RemoteAccountProfileUpdateRequest, RemoteAccountView, RemoteBrowserAuthPollRequest, RemoteBrowserAuthPollResult, RemoteBrowserAuthStartRequest, RemoteBrowserAuthStartResult, RemoteDoctorCheckView, RemoteDoctorView, RemoteLoginRequest, RemoteRuntimeView, RemoteServiceAction, RemoteServiceActionResult, RemoteServiceView, RemoteSettingsUpdateRequest, RemoteSettingsView, RuntimeConfigUpdate, SearchConfigUpdate, SearchConfigView, SearchProviderConfigView, SearchProviderName, SearchProviderSpecView, SecretProviderEnvView, SecretProviderExecView, SecretProviderFileView, SecretProviderView, SecretRefView, SecretSourceView, SecretsConfigUpdate, SecretsView, ServerPathBreadcrumbView, ServerPathBrowseView, ServerPathEntryView, SessionConfigView, SessionEntryView, SessionEventView, SessionHistoryView, SessionMessageView, SessionPatchUpdate, SessionPatchValidationError, SessionSkillEntryView, SessionTypeDescribeParams, SessionsListView, TavilySearchDepthValue, UiNcpAgent, UiNcpAssetPutView, UiNcpAssetView, UiNcpSessionListView, UiNcpSessionMessagesView, UiNcpSessionService, UiNcpStoredAssetRecord, type UiRemoteAccessHost, UiServerEvent, UiServerHandle, UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createCustomProvider, createUiRouter, deleteCustomProvider, deleteSession, ensureUiBridgeSecret, executeConfigAction, getSessionHistory, getUiBridgeSecretPath, listSessions, loadConfigOrDefault, patchSession, readUiBridgeSecret, startUiServer, testProviderConnection, updateChannel, updateModel, updateProvider, updateRuntime, updateSearch, updateSecrets };
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
6
6
|
import { readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
7
7
|
import { dirname, isAbsolute, join, parse, resolve } from "node:path";
|
|
8
8
|
import * as NextclawCore from "@nextclaw/core";
|
|
9
|
-
import { ConfigSchema, DEFAULT_WORKSPACE_PATH, LiteLLMProvider, SessionManager, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, getWorkspacePathFromConfig, hasSecretRef, isSensitiveConfigPath, loadConfig, normalizeThinkingLevels, parseThinkingLevel, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig } from "@nextclaw/core";
|
|
9
|
+
import { ConfigSchema, DEFAULT_WORKSPACE_PATH, LiteLLMProvider, SessionManager, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, getWorkspacePathFromConfig, hasSecretRef, isSensitiveConfigPath, loadConfig, normalizeThinkingLevels, parseThinkingLevel, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig, updateAgentProfile } from "@nextclaw/core";
|
|
10
10
|
import { createHash, randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
11
11
|
import { mountNcpHttpAgentRoutes } from "@nextclaw/ncp-http-agent-server";
|
|
12
12
|
import { discoverPluginStatusReport, enablePluginInConfig, mergePluginConfigView, toPluginConfigView } from "@nextclaw/openclaw-compat";
|
|
@@ -291,7 +291,10 @@ function createAgent(configPath, input, options = {}) {
|
|
|
291
291
|
displayName: input.displayName,
|
|
292
292
|
description: input.description,
|
|
293
293
|
avatar: input.avatar,
|
|
294
|
-
home: input.home
|
|
294
|
+
home: input.home,
|
|
295
|
+
model: input.model,
|
|
296
|
+
runtime: input.runtime,
|
|
297
|
+
runtimeConfig: input.runtimeConfig
|
|
295
298
|
}, {
|
|
296
299
|
configPath,
|
|
297
300
|
initializeHomeDirectory: options.initializeAgentHomeDirectory
|
|
@@ -305,6 +308,18 @@ function deleteAgent(configPath, agentId) {
|
|
|
305
308
|
agentId: agentId.trim().toLowerCase()
|
|
306
309
|
};
|
|
307
310
|
}
|
|
311
|
+
function updateAgent(configPath, agentId, input) {
|
|
312
|
+
const updated = updateAgentProfile({
|
|
313
|
+
id: agentId,
|
|
314
|
+
displayName: input.displayName,
|
|
315
|
+
description: input.description,
|
|
316
|
+
avatar: input.avatar,
|
|
317
|
+
model: input.model,
|
|
318
|
+
runtime: input.runtime,
|
|
319
|
+
runtimeConfig: input.runtimeConfig
|
|
320
|
+
}, { configPath });
|
|
321
|
+
return toAgentProfileView(loadConfig(configPath), updated.id);
|
|
322
|
+
}
|
|
308
323
|
function readAgentAvatar(configPath, agentId) {
|
|
309
324
|
return readAgentAvatarContent({
|
|
310
325
|
config: loadConfig(configPath),
|
|
@@ -323,6 +338,8 @@ function toAgentProfileView(config, agentId) {
|
|
|
323
338
|
avatarUrl: buildAgentAvatarUrl(profile.id, profile.avatar),
|
|
324
339
|
workspace: profile.workspace,
|
|
325
340
|
model: profile.model,
|
|
341
|
+
runtime: profile.runtime,
|
|
342
|
+
runtimeConfig: profile.runtimeConfig,
|
|
326
343
|
engine: profile.engine,
|
|
327
344
|
engineConfig: profile.engineConfig,
|
|
328
345
|
contextTokens: profile.contextTokens,
|
|
@@ -410,6 +427,20 @@ var AgentsRoutesController = class {
|
|
|
410
427
|
return c.json(err("AGENT_CREATE_FAILED", error instanceof Error ? error.message : String(error)), 400);
|
|
411
428
|
}
|
|
412
429
|
};
|
|
430
|
+
updateAgent = async (c) => {
|
|
431
|
+
const agentId = c.req.param("agentId");
|
|
432
|
+
const body = await readJson(c.req.raw);
|
|
433
|
+
if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
434
|
+
try {
|
|
435
|
+
const agent = updateAgent(this.options.configPath, agentId, body.data);
|
|
436
|
+
await this.publishAgentUpdates(["agents.list"]);
|
|
437
|
+
return c.json(ok(agent));
|
|
438
|
+
} catch (error) {
|
|
439
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
440
|
+
const status = message.includes("not found") ? 404 : 400;
|
|
441
|
+
return c.json(err("AGENT_UPDATE_FAILED", message), status);
|
|
442
|
+
}
|
|
443
|
+
};
|
|
413
444
|
deleteAgent = async (c) => {
|
|
414
445
|
const agentId = c.req.param("agentId");
|
|
415
446
|
try {
|
|
@@ -766,6 +797,230 @@ function findServerBuiltinProviderByName(name) {
|
|
|
766
797
|
return SERVER_BUILTIN_PROVIDER_OVERRIDE_MAP.get(name) ?? findBuiltinProviderByName(name);
|
|
767
798
|
}
|
|
768
799
|
//#endregion
|
|
800
|
+
//#region src/ui/search-config.ts
|
|
801
|
+
const MASK_MIN_LENGTH$1 = 8;
|
|
802
|
+
const BOCHA_OPEN_URL = "https://open.bocha.cn";
|
|
803
|
+
const TAVILY_DOCS_URL = "https://docs.tavily.com/documentation/api-reference/endpoint/search";
|
|
804
|
+
const SEARCH_PROVIDER_NAMES = [
|
|
805
|
+
"bocha",
|
|
806
|
+
"tavily",
|
|
807
|
+
"brave"
|
|
808
|
+
];
|
|
809
|
+
function normalizeOptionalString$1(value) {
|
|
810
|
+
if (typeof value !== "string") return null;
|
|
811
|
+
const trimmed = value.trim();
|
|
812
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
813
|
+
}
|
|
814
|
+
function maskApiKey$1(value) {
|
|
815
|
+
if (!value) return { apiKeySet: false };
|
|
816
|
+
if (value.length < MASK_MIN_LENGTH$1) return {
|
|
817
|
+
apiKeySet: true,
|
|
818
|
+
apiKeyMasked: "****"
|
|
819
|
+
};
|
|
820
|
+
return {
|
|
821
|
+
apiKeySet: true,
|
|
822
|
+
apiKeyMasked: `${value.slice(0, 2)}****${value.slice(-4)}`
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
function clearSecretRef$1(refs, path) {
|
|
826
|
+
if (!refs[path]) return refs;
|
|
827
|
+
const nextRefs = { ...refs };
|
|
828
|
+
delete nextRefs[path];
|
|
829
|
+
return nextRefs;
|
|
830
|
+
}
|
|
831
|
+
function isSearchProviderName(value) {
|
|
832
|
+
return typeof value === "string" && SEARCH_PROVIDER_NAMES.some((providerName) => providerName === value);
|
|
833
|
+
}
|
|
834
|
+
const SEARCH_PROVIDER_META = [
|
|
835
|
+
{
|
|
836
|
+
name: "bocha",
|
|
837
|
+
displayName: "Bocha Search",
|
|
838
|
+
description: "China-friendly web search with AI-ready summaries.",
|
|
839
|
+
docsUrl: BOCHA_OPEN_URL,
|
|
840
|
+
isDefault: true,
|
|
841
|
+
supportsSummary: true
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
name: "tavily",
|
|
845
|
+
displayName: "Tavily Search",
|
|
846
|
+
description: "Research-focused web search with optional synthesized answers.",
|
|
847
|
+
docsUrl: TAVILY_DOCS_URL,
|
|
848
|
+
supportsSummary: true
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
name: "brave",
|
|
852
|
+
displayName: "Brave Search",
|
|
853
|
+
description: "Brave web search API kept as an optional provider.",
|
|
854
|
+
supportsSummary: false
|
|
855
|
+
}
|
|
856
|
+
];
|
|
857
|
+
function toSearchProviderView(config, providerName, provider) {
|
|
858
|
+
const apiKeyRefSet = hasSecretRef(config, `search.providers.${providerName}.apiKey`);
|
|
859
|
+
const masked = maskApiKey$1(provider.apiKey);
|
|
860
|
+
const view = {
|
|
861
|
+
enabled: config.search.enabledProviders.includes(providerName),
|
|
862
|
+
apiKeySet: masked.apiKeySet || apiKeyRefSet,
|
|
863
|
+
apiKeyMasked: masked.apiKeyMasked ?? (apiKeyRefSet ? "****" : void 0),
|
|
864
|
+
baseUrl: provider.baseUrl
|
|
865
|
+
};
|
|
866
|
+
if ("docsUrl" in provider) view.docsUrl = provider.docsUrl;
|
|
867
|
+
if ("summary" in provider) view.summary = provider.summary;
|
|
868
|
+
if ("freshness" in provider) view.freshness = provider.freshness;
|
|
869
|
+
if ("searchDepth" in provider) view.searchDepth = provider.searchDepth;
|
|
870
|
+
if ("includeAnswer" in provider) view.includeAnswer = Boolean(provider.includeAnswer);
|
|
871
|
+
return view;
|
|
872
|
+
}
|
|
873
|
+
function buildSearchView(config) {
|
|
874
|
+
return {
|
|
875
|
+
provider: config.search.provider,
|
|
876
|
+
enabledProviders: [...config.search.enabledProviders],
|
|
877
|
+
defaults: { maxResults: config.search.defaults.maxResults },
|
|
878
|
+
providers: {
|
|
879
|
+
bocha: toSearchProviderView(config, "bocha", config.search.providers.bocha),
|
|
880
|
+
tavily: toSearchProviderView(config, "tavily", config.search.providers.tavily),
|
|
881
|
+
brave: toSearchProviderView(config, "brave", config.search.providers.brave)
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
function replaceSearchConfig(config, search, refs = config.secrets.refs) {
|
|
886
|
+
return {
|
|
887
|
+
...config,
|
|
888
|
+
search,
|
|
889
|
+
secrets: refs === config.secrets.refs ? config.secrets : {
|
|
890
|
+
...config.secrets,
|
|
891
|
+
refs
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
function applyActiveSearchProviderPatch(config, provider) {
|
|
896
|
+
if (!isSearchProviderName(provider)) return config;
|
|
897
|
+
return replaceSearchConfig(config, {
|
|
898
|
+
...config.search,
|
|
899
|
+
provider
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
function applyEnabledSearchProvidersPatch(config, enabledProviders) {
|
|
903
|
+
if (!Array.isArray(enabledProviders)) return config;
|
|
904
|
+
const nextEnabledProviders = Array.from(new Set(enabledProviders.filter((value) => isSearchProviderName(value))));
|
|
905
|
+
return replaceSearchConfig(config, {
|
|
906
|
+
...config.search,
|
|
907
|
+
enabledProviders: nextEnabledProviders
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
function applySearchDefaultsPatch(config, defaults) {
|
|
911
|
+
if (!defaults || !Object.prototype.hasOwnProperty.call(defaults, "maxResults")) return config;
|
|
912
|
+
const nextMaxResults = defaults.maxResults;
|
|
913
|
+
if (typeof nextMaxResults === "number" && Number.isFinite(nextMaxResults)) return replaceSearchConfig(config, {
|
|
914
|
+
...config.search,
|
|
915
|
+
defaults: {
|
|
916
|
+
...config.search.defaults,
|
|
917
|
+
maxResults: Math.max(1, Math.min(50, Math.trunc(nextMaxResults)))
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
return config;
|
|
921
|
+
}
|
|
922
|
+
function applyBochaSearchPatch(config, patch) {
|
|
923
|
+
if (!patch) return config;
|
|
924
|
+
let nextRefs = config.secrets.refs;
|
|
925
|
+
let nextProvider = config.search.providers.bocha;
|
|
926
|
+
if (Object.prototype.hasOwnProperty.call(patch, "apiKey")) {
|
|
927
|
+
nextProvider = {
|
|
928
|
+
...nextProvider,
|
|
929
|
+
apiKey: patch.apiKey ?? ""
|
|
930
|
+
};
|
|
931
|
+
nextRefs = clearSecretRef$1(nextRefs, "search.providers.bocha.apiKey");
|
|
932
|
+
}
|
|
933
|
+
if (Object.prototype.hasOwnProperty.call(patch, "baseUrl")) nextProvider = {
|
|
934
|
+
...nextProvider,
|
|
935
|
+
baseUrl: normalizeOptionalString$1(patch.baseUrl) ?? "https://api.bocha.cn/v1/web-search"
|
|
936
|
+
};
|
|
937
|
+
if (Object.prototype.hasOwnProperty.call(patch, "docsUrl")) nextProvider = {
|
|
938
|
+
...nextProvider,
|
|
939
|
+
docsUrl: normalizeOptionalString$1(patch.docsUrl) ?? BOCHA_OPEN_URL
|
|
940
|
+
};
|
|
941
|
+
if (Object.prototype.hasOwnProperty.call(patch, "summary")) nextProvider = {
|
|
942
|
+
...nextProvider,
|
|
943
|
+
summary: Boolean(patch.summary)
|
|
944
|
+
};
|
|
945
|
+
if (Object.prototype.hasOwnProperty.call(patch, "freshness")) {
|
|
946
|
+
const freshness = normalizeOptionalString$1(patch.freshness);
|
|
947
|
+
nextProvider = {
|
|
948
|
+
...nextProvider,
|
|
949
|
+
freshness: freshness === "noLimit" || freshness === "oneDay" || freshness === "oneWeek" || freshness === "oneMonth" || freshness === "oneYear" ? freshness : "noLimit"
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
return replaceSearchConfig(config, {
|
|
953
|
+
...config.search,
|
|
954
|
+
providers: {
|
|
955
|
+
...config.search.providers,
|
|
956
|
+
bocha: nextProvider
|
|
957
|
+
}
|
|
958
|
+
}, nextRefs);
|
|
959
|
+
}
|
|
960
|
+
function applyTavilySearchPatch(config, patch) {
|
|
961
|
+
if (!patch) return config;
|
|
962
|
+
let nextRefs = config.secrets.refs;
|
|
963
|
+
let nextProvider = config.search.providers.tavily;
|
|
964
|
+
if (Object.prototype.hasOwnProperty.call(patch, "apiKey")) {
|
|
965
|
+
nextProvider = {
|
|
966
|
+
...nextProvider,
|
|
967
|
+
apiKey: patch.apiKey ?? ""
|
|
968
|
+
};
|
|
969
|
+
nextRefs = clearSecretRef$1(nextRefs, "search.providers.tavily.apiKey");
|
|
970
|
+
}
|
|
971
|
+
if (Object.prototype.hasOwnProperty.call(patch, "baseUrl")) nextProvider = {
|
|
972
|
+
...nextProvider,
|
|
973
|
+
baseUrl: normalizeOptionalString$1(patch.baseUrl) ?? "https://api.tavily.com/search"
|
|
974
|
+
};
|
|
975
|
+
if (Object.prototype.hasOwnProperty.call(patch, "searchDepth")) {
|
|
976
|
+
const searchDepth = normalizeOptionalString$1(patch.searchDepth);
|
|
977
|
+
nextProvider = {
|
|
978
|
+
...nextProvider,
|
|
979
|
+
searchDepth: searchDepth === "advanced" ? "advanced" : "basic"
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
if (Object.prototype.hasOwnProperty.call(patch, "includeAnswer")) nextProvider = {
|
|
983
|
+
...nextProvider,
|
|
984
|
+
includeAnswer: Boolean(patch.includeAnswer)
|
|
985
|
+
};
|
|
986
|
+
return replaceSearchConfig(config, {
|
|
987
|
+
...config.search,
|
|
988
|
+
providers: {
|
|
989
|
+
...config.search.providers,
|
|
990
|
+
tavily: nextProvider
|
|
991
|
+
}
|
|
992
|
+
}, nextRefs);
|
|
993
|
+
}
|
|
994
|
+
function applyBraveSearchPatch(config, patch) {
|
|
995
|
+
if (!patch) return config;
|
|
996
|
+
let nextRefs = config.secrets.refs;
|
|
997
|
+
let nextProvider = config.search.providers.brave;
|
|
998
|
+
if (Object.prototype.hasOwnProperty.call(patch, "apiKey")) {
|
|
999
|
+
nextProvider = {
|
|
1000
|
+
...nextProvider,
|
|
1001
|
+
apiKey: patch.apiKey ?? ""
|
|
1002
|
+
};
|
|
1003
|
+
nextRefs = clearSecretRef$1(nextRefs, "search.providers.brave.apiKey");
|
|
1004
|
+
}
|
|
1005
|
+
if (Object.prototype.hasOwnProperty.call(patch, "baseUrl")) nextProvider = {
|
|
1006
|
+
...nextProvider,
|
|
1007
|
+
baseUrl: normalizeOptionalString$1(patch.baseUrl) ?? "https://api.search.brave.com/res/v1/web/search"
|
|
1008
|
+
};
|
|
1009
|
+
return replaceSearchConfig(config, {
|
|
1010
|
+
...config.search,
|
|
1011
|
+
providers: {
|
|
1012
|
+
...config.search.providers,
|
|
1013
|
+
brave: nextProvider
|
|
1014
|
+
}
|
|
1015
|
+
}, nextRefs);
|
|
1016
|
+
}
|
|
1017
|
+
function updateSearch(configPath, patch) {
|
|
1018
|
+
const nextConfig = applyBraveSearchPatch(applyTavilySearchPatch(applyBochaSearchPatch(applySearchDefaultsPatch(applyEnabledSearchProvidersPatch(applyActiveSearchProviderPatch(loadConfig(configPath), patch.provider), patch.enabledProviders), patch.defaults), patch.providers?.bocha), patch.providers?.tavily), patch.providers?.brave);
|
|
1019
|
+
const next = ConfigSchema.parse(nextConfig);
|
|
1020
|
+
saveConfig(next, configPath);
|
|
1021
|
+
return buildSearchView(next);
|
|
1022
|
+
}
|
|
1023
|
+
//#endregion
|
|
769
1024
|
//#region src/ui/session-preference-patch.ts
|
|
770
1025
|
function applySessionPreferencePatch(params) {
|
|
771
1026
|
const nextMetadata = params.metadata;
|
|
@@ -876,20 +1131,6 @@ function ensureProviderConfig(config, providerName) {
|
|
|
876
1131
|
function clearSecretRefsByPrefix(config, pathPrefix) {
|
|
877
1132
|
for (const key of Object.keys(config.secrets.refs)) if (key === pathPrefix || key.startsWith(`${pathPrefix}.`)) delete config.secrets.refs[key];
|
|
878
1133
|
}
|
|
879
|
-
const BOCHA_OPEN_URL = "https://open.bocha.cn";
|
|
880
|
-
const SEARCH_PROVIDER_META = [{
|
|
881
|
-
name: "bocha",
|
|
882
|
-
displayName: "Bocha Search",
|
|
883
|
-
description: "China-friendly web search with AI-ready summaries.",
|
|
884
|
-
docsUrl: BOCHA_OPEN_URL,
|
|
885
|
-
isDefault: true,
|
|
886
|
-
supportsSummary: true
|
|
887
|
-
}, {
|
|
888
|
-
name: "brave",
|
|
889
|
-
displayName: "Brave Search",
|
|
890
|
-
description: "Brave web search API kept as an optional provider.",
|
|
891
|
-
supportsSummary: false
|
|
892
|
-
}];
|
|
893
1134
|
function matchesExtraSensitivePath(path) {
|
|
894
1135
|
if (path === "session" || path.startsWith("session.")) return false;
|
|
895
1136
|
return EXTRA_SENSITIVE_PATH_PATTERNS.some((pattern) => pattern.test(path));
|
|
@@ -1106,31 +1347,6 @@ function buildConfigView(config, options) {
|
|
|
1106
1347
|
}
|
|
1107
1348
|
};
|
|
1108
1349
|
}
|
|
1109
|
-
function toSearchProviderView(config, providerName, provider) {
|
|
1110
|
-
const apiKeyRefSet = hasSecretRef(config, `search.providers.${providerName}.apiKey`);
|
|
1111
|
-
const masked = maskApiKey(provider.apiKey);
|
|
1112
|
-
const base = {
|
|
1113
|
-
enabled: config.search.enabledProviders.includes(providerName),
|
|
1114
|
-
apiKeySet: masked.apiKeySet || apiKeyRefSet,
|
|
1115
|
-
apiKeyMasked: masked.apiKeyMasked ?? (apiKeyRefSet ? "****" : void 0),
|
|
1116
|
-
baseUrl: provider.baseUrl
|
|
1117
|
-
};
|
|
1118
|
-
if ("docsUrl" in provider) base.docsUrl = provider.docsUrl;
|
|
1119
|
-
if ("summary" in provider) base.summary = provider.summary;
|
|
1120
|
-
if ("freshness" in provider) base.freshness = provider.freshness;
|
|
1121
|
-
return base;
|
|
1122
|
-
}
|
|
1123
|
-
function buildSearchView(config) {
|
|
1124
|
-
return {
|
|
1125
|
-
provider: config.search.provider,
|
|
1126
|
-
enabledProviders: [...config.search.enabledProviders],
|
|
1127
|
-
defaults: { maxResults: config.search.defaults.maxResults },
|
|
1128
|
-
providers: {
|
|
1129
|
-
bocha: toSearchProviderView(config, "bocha", config.search.providers.bocha),
|
|
1130
|
-
brave: toSearchProviderView(config, "brave", config.search.providers.brave)
|
|
1131
|
-
}
|
|
1132
|
-
};
|
|
1133
|
-
}
|
|
1134
1350
|
function clearSecretRef(config, path) {
|
|
1135
1351
|
if (config.secrets.refs[path]) delete config.secrets.refs[path];
|
|
1136
1352
|
}
|
|
@@ -1266,41 +1482,6 @@ function updateModel(configPath, patch) {
|
|
|
1266
1482
|
saveConfig(next, configPath);
|
|
1267
1483
|
return buildConfigView(next);
|
|
1268
1484
|
}
|
|
1269
|
-
function updateSearch(configPath, patch) {
|
|
1270
|
-
const config = loadConfigOrDefault(configPath);
|
|
1271
|
-
if (patch.provider === "bocha" || patch.provider === "brave") config.search.provider = patch.provider;
|
|
1272
|
-
if (Array.isArray(patch.enabledProviders)) config.search.enabledProviders = Array.from(new Set(patch.enabledProviders.filter((value) => value === "bocha" || value === "brave")));
|
|
1273
|
-
if (patch.defaults && Object.prototype.hasOwnProperty.call(patch.defaults, "maxResults")) {
|
|
1274
|
-
const nextMaxResults = patch.defaults.maxResults;
|
|
1275
|
-
if (typeof nextMaxResults === "number" && Number.isFinite(nextMaxResults)) config.search.defaults.maxResults = Math.max(1, Math.min(50, Math.trunc(nextMaxResults)));
|
|
1276
|
-
}
|
|
1277
|
-
const bochaPatch = patch.providers?.bocha;
|
|
1278
|
-
if (bochaPatch) {
|
|
1279
|
-
if (Object.prototype.hasOwnProperty.call(bochaPatch, "apiKey")) {
|
|
1280
|
-
config.search.providers.bocha.apiKey = bochaPatch.apiKey ?? "";
|
|
1281
|
-
clearSecretRef(config, "search.providers.bocha.apiKey");
|
|
1282
|
-
}
|
|
1283
|
-
if (Object.prototype.hasOwnProperty.call(bochaPatch, "baseUrl")) config.search.providers.bocha.baseUrl = normalizeOptionalString(bochaPatch.baseUrl) ?? "https://api.bocha.cn/v1/web-search";
|
|
1284
|
-
if (Object.prototype.hasOwnProperty.call(bochaPatch, "docsUrl")) config.search.providers.bocha.docsUrl = normalizeOptionalString(bochaPatch.docsUrl) ?? BOCHA_OPEN_URL;
|
|
1285
|
-
if (Object.prototype.hasOwnProperty.call(bochaPatch, "summary")) config.search.providers.bocha.summary = Boolean(bochaPatch.summary);
|
|
1286
|
-
if (Object.prototype.hasOwnProperty.call(bochaPatch, "freshness")) {
|
|
1287
|
-
const freshness = normalizeOptionalString(bochaPatch.freshness);
|
|
1288
|
-
if (freshness === "noLimit" || freshness === "oneDay" || freshness === "oneWeek" || freshness === "oneMonth" || freshness === "oneYear") config.search.providers.bocha.freshness = freshness;
|
|
1289
|
-
else config.search.providers.bocha.freshness = "noLimit";
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
const bravePatch = patch.providers?.brave;
|
|
1293
|
-
if (bravePatch) {
|
|
1294
|
-
if (Object.prototype.hasOwnProperty.call(bravePatch, "apiKey")) {
|
|
1295
|
-
config.search.providers.brave.apiKey = bravePatch.apiKey ?? "";
|
|
1296
|
-
clearSecretRef(config, "search.providers.brave.apiKey");
|
|
1297
|
-
}
|
|
1298
|
-
if (Object.prototype.hasOwnProperty.call(bravePatch, "baseUrl")) config.search.providers.brave.baseUrl = normalizeOptionalString(bravePatch.baseUrl) ?? "https://api.search.brave.com/res/v1/web/search";
|
|
1299
|
-
}
|
|
1300
|
-
const next = ConfigSchema.parse(config);
|
|
1301
|
-
saveConfig(next, configPath);
|
|
1302
|
-
return buildSearchView(next);
|
|
1303
|
-
}
|
|
1304
1485
|
function updateProvider(configPath, providerName, patch) {
|
|
1305
1486
|
const config = loadConfigOrDefault(configPath);
|
|
1306
1487
|
const provider = ensureProviderConfig(config, providerName);
|
|
@@ -1495,13 +1676,14 @@ function createSessionManager(config) {
|
|
|
1495
1676
|
}
|
|
1496
1677
|
const DEFAULT_SESSION_TYPE = "native";
|
|
1497
1678
|
const SESSION_TYPE_METADATA_KEY = "session_type";
|
|
1679
|
+
const RUNTIME_METADATA_KEY = "runtime";
|
|
1498
1680
|
function normalizeSessionType(value) {
|
|
1499
1681
|
if (typeof value !== "string") return null;
|
|
1500
1682
|
const normalized = value.trim().toLowerCase();
|
|
1501
1683
|
return normalized.length > 0 ? normalized : null;
|
|
1502
1684
|
}
|
|
1503
1685
|
function readSessionType(session) {
|
|
1504
|
-
return normalizeSessionType(session.metadata[SESSION_TYPE_METADATA_KEY]) ?? "native";
|
|
1686
|
+
return normalizeSessionType(session.metadata[RUNTIME_METADATA_KEY]) ?? normalizeSessionType(session.metadata[SESSION_TYPE_METADATA_KEY]) ?? "native";
|
|
1505
1687
|
}
|
|
1506
1688
|
function countUserMessages(session) {
|
|
1507
1689
|
return session.messages.reduce((total, message) => {
|
|
@@ -1642,6 +1824,7 @@ function patchSession(configPath, key, patch, options) {
|
|
|
1642
1824
|
availableSessionTypes.add(DEFAULT_SESSION_TYPE);
|
|
1643
1825
|
if (!availableSessionTypes.has(normalizedSessionType)) throw new SessionPatchValidationError("SESSION_TYPE_UNAVAILABLE", `sessionType is unavailable: ${normalizedSessionType}`);
|
|
1644
1826
|
session.metadata[SESSION_TYPE_METADATA_KEY] = normalizedSessionType;
|
|
1827
|
+
session.metadata[RUNTIME_METADATA_KEY] = normalizedSessionType;
|
|
1645
1828
|
}
|
|
1646
1829
|
session.updatedAt = /* @__PURE__ */ new Date();
|
|
1647
1830
|
sessionManager.save(session);
|
|
@@ -2449,6 +2632,56 @@ function buildCronJobView(job) {
|
|
|
2449
2632
|
function findCronJob(service, id) {
|
|
2450
2633
|
return service.listJobs(true).find((job) => job.id === id) ?? null;
|
|
2451
2634
|
}
|
|
2635
|
+
function normalizeCronSchedule(schedule) {
|
|
2636
|
+
if (!schedule) return null;
|
|
2637
|
+
if (schedule.kind === "every") {
|
|
2638
|
+
if (typeof schedule.everyMs !== "number" || !Number.isFinite(schedule.everyMs) || schedule.everyMs <= 0) return null;
|
|
2639
|
+
return {
|
|
2640
|
+
kind: "every",
|
|
2641
|
+
everyMs: schedule.everyMs
|
|
2642
|
+
};
|
|
2643
|
+
}
|
|
2644
|
+
if (schedule.kind === "at") {
|
|
2645
|
+
if (typeof schedule.atMs !== "number" || !Number.isFinite(schedule.atMs)) return null;
|
|
2646
|
+
return {
|
|
2647
|
+
kind: "at",
|
|
2648
|
+
atMs: schedule.atMs
|
|
2649
|
+
};
|
|
2650
|
+
}
|
|
2651
|
+
if (schedule.kind === "cron") {
|
|
2652
|
+
const expr = readNonEmptyString(schedule.expr);
|
|
2653
|
+
if (!expr) return null;
|
|
2654
|
+
const tz = readNonEmptyString(schedule.tz);
|
|
2655
|
+
return tz ? {
|
|
2656
|
+
kind: "cron",
|
|
2657
|
+
expr,
|
|
2658
|
+
tz
|
|
2659
|
+
} : {
|
|
2660
|
+
kind: "cron",
|
|
2661
|
+
expr
|
|
2662
|
+
};
|
|
2663
|
+
}
|
|
2664
|
+
return null;
|
|
2665
|
+
}
|
|
2666
|
+
function readCronCreateParams(input) {
|
|
2667
|
+
const name = readNonEmptyString(input.name);
|
|
2668
|
+
if (!name) return { error: "name must be a non-empty string" };
|
|
2669
|
+
const message = readNonEmptyString(input.message);
|
|
2670
|
+
if (!message) return { error: "message must be a non-empty string" };
|
|
2671
|
+
const schedule = normalizeCronSchedule(input.schedule);
|
|
2672
|
+
if (!schedule) return { error: "schedule must be a valid at/every/cron definition" };
|
|
2673
|
+
return { params: {
|
|
2674
|
+
name,
|
|
2675
|
+
message,
|
|
2676
|
+
schedule,
|
|
2677
|
+
agentId: readNonEmptyString(input.agentId),
|
|
2678
|
+
deliver: input.deliver === true,
|
|
2679
|
+
channel: readNonEmptyString(input.channel),
|
|
2680
|
+
to: readNonEmptyString(input.to),
|
|
2681
|
+
accountId: readNonEmptyString(input.accountId),
|
|
2682
|
+
deleteAfterRun: input.deleteAfterRun === true
|
|
2683
|
+
} };
|
|
2684
|
+
}
|
|
2452
2685
|
var CronRoutesController = class {
|
|
2453
2686
|
constructor(options) {
|
|
2454
2687
|
this.options = options;
|
|
@@ -2463,6 +2696,15 @@ var CronRoutesController = class {
|
|
|
2463
2696
|
total: jobs.length
|
|
2464
2697
|
}));
|
|
2465
2698
|
};
|
|
2699
|
+
createJob = async (c) => {
|
|
2700
|
+
if (!this.options.cronService) return c.json(err("NOT_AVAILABLE", "cron service unavailable"), 503);
|
|
2701
|
+
const body = await readJson(c.req.raw);
|
|
2702
|
+
if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
2703
|
+
const normalized = readCronCreateParams(body.data);
|
|
2704
|
+
if ("error" in normalized) return c.json(err("INVALID_BODY", normalized.error), 400);
|
|
2705
|
+
const data = { job: buildCronJobView(this.options.cronService.addJob(normalized.params)) };
|
|
2706
|
+
return c.json(ok(data), 201);
|
|
2707
|
+
};
|
|
2466
2708
|
deleteJob = (c) => {
|
|
2467
2709
|
if (!this.options.cronService) return c.json(err("NOT_AVAILABLE", "cron service unavailable"), 503);
|
|
2468
2710
|
const id = decodeURIComponent(c.req.param("id"));
|
|
@@ -2554,7 +2796,6 @@ var NcpAssetRoutesController = class {
|
|
|
2554
2796
|
if (!record || !contentPath) return c.json(err("NOT_FOUND", `asset not found: ${uri}`), 404);
|
|
2555
2797
|
const body = await readFile(contentPath);
|
|
2556
2798
|
return new Response(body, { headers: {
|
|
2557
|
-
"content-length": String(body.byteLength),
|
|
2558
2799
|
"content-type": record.mimeType || "application/octet-stream",
|
|
2559
2800
|
"content-disposition": `inline; filename*=UTF-8''${encodeContentDispositionFileName(record.fileName)}`
|
|
2560
2801
|
} });
|
|
@@ -2738,9 +2979,11 @@ function applySessionTypePatch(metadata, patch) {
|
|
|
2738
2979
|
const sessionType = typeof patch.sessionType === "string" ? patch.sessionType.trim() : "";
|
|
2739
2980
|
if (sessionType) {
|
|
2740
2981
|
metadata.session_type = sessionType;
|
|
2982
|
+
metadata.runtime = sessionType;
|
|
2741
2983
|
delete metadata.sessionType;
|
|
2742
2984
|
return;
|
|
2743
2985
|
}
|
|
2986
|
+
delete metadata.runtime;
|
|
2744
2987
|
delete metadata.session_type;
|
|
2745
2988
|
delete metadata.sessionType;
|
|
2746
2989
|
}
|
|
@@ -4048,6 +4291,17 @@ var RemoteRoutesController = class {
|
|
|
4048
4291
|
return c.json(err("REMOTE_LOGOUT_FAILED", formatUserFacingError(error)), 500);
|
|
4049
4292
|
}
|
|
4050
4293
|
};
|
|
4294
|
+
updateProfile = async (c) => {
|
|
4295
|
+
const body = await readJson(c.req.raw);
|
|
4296
|
+
if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
4297
|
+
const username = readNonEmptyString(body.data.username);
|
|
4298
|
+
if (!username) return c.json(err("INVALID_BODY", "username is required"), 400);
|
|
4299
|
+
try {
|
|
4300
|
+
return c.json(ok(await this.host.updateProfile({ username })));
|
|
4301
|
+
} catch (error) {
|
|
4302
|
+
return c.json(err("REMOTE_PROFILE_UPDATE_FAILED", formatUserFacingError(error)), 400);
|
|
4303
|
+
}
|
|
4304
|
+
};
|
|
4051
4305
|
updateSettings = async (c) => {
|
|
4052
4306
|
const body = await readJson(c.req.raw);
|
|
4053
4307
|
if (!body.ok) return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
@@ -4190,6 +4444,7 @@ function registerAuthRoutes(app, authController) {
|
|
|
4190
4444
|
function registerAgentRoutes(app, agentsController) {
|
|
4191
4445
|
app.get("/api/agents", agentsController.listAgents);
|
|
4192
4446
|
app.post("/api/agents", agentsController.createAgent);
|
|
4447
|
+
app.put("/api/agents/:agentId", agentsController.updateAgent);
|
|
4193
4448
|
app.delete("/api/agents/:agentId", agentsController.deleteAgent);
|
|
4194
4449
|
app.get("/api/agents/:agentId/avatar", agentsController.getAgentAvatar);
|
|
4195
4450
|
}
|
|
@@ -4237,6 +4492,7 @@ function registerNcpRuntimeRoutes(app, options, ncpAssetController) {
|
|
|
4237
4492
|
}
|
|
4238
4493
|
function registerCronRoutes(app, cronController) {
|
|
4239
4494
|
app.get("/api/cron", cronController.listJobs);
|
|
4495
|
+
app.post("/api/cron", cronController.createJob);
|
|
4240
4496
|
app.delete("/api/cron/:id", cronController.deleteJob);
|
|
4241
4497
|
app.put("/api/cron/:id/enable", cronController.enableJob);
|
|
4242
4498
|
app.post("/api/cron/:id/run", cronController.runJob);
|
|
@@ -4249,6 +4505,7 @@ function registerRemoteRoutes(app, remoteController) {
|
|
|
4249
4505
|
app.post("/api/remote/auth/start", remoteController.startBrowserAuth);
|
|
4250
4506
|
app.post("/api/remote/auth/poll", remoteController.pollBrowserAuth);
|
|
4251
4507
|
app.post("/api/remote/logout", remoteController.logout);
|
|
4508
|
+
app.put("/api/remote/account/profile", remoteController.updateProfile);
|
|
4252
4509
|
app.put("/api/remote/settings", remoteController.updateSettings);
|
|
4253
4510
|
app.post("/api/remote/service/:action", remoteController.controlService);
|
|
4254
4511
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Nextclaw UI/API server.",
|
|
6
6
|
"type": "module",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"@hono/node-server": "^1.13.3",
|
|
19
19
|
"hono": "^4.6.2",
|
|
20
20
|
"ws": "^8.18.0",
|
|
21
|
-
"@nextclaw/
|
|
22
|
-
"@nextclaw/
|
|
23
|
-
"@nextclaw/
|
|
24
|
-
"@nextclaw/
|
|
21
|
+
"@nextclaw/core": "0.12.3",
|
|
22
|
+
"@nextclaw/mcp": "0.1.68",
|
|
23
|
+
"@nextclaw/ncp-http-agent-server": "0.3.12",
|
|
24
|
+
"@nextclaw/openclaw-compat": "1.0.3",
|
|
25
25
|
"@nextclaw/ncp": "0.5.0",
|
|
26
|
-
"@nextclaw/
|
|
26
|
+
"@nextclaw/runtime": "0.2.35"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^20.17.6",
|