@nextclaw/server 0.5.3 → 0.5.6
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 +54 -2
- package/dist/index.js +115 -10
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import * as NextclawCore from '@nextclaw/core';
|
|
2
|
+
import { CronService, Config, ConfigActionExecuteRequest as ConfigActionExecuteRequest$1, ConfigActionExecuteResult as ConfigActionExecuteResult$1 } from '@nextclaw/core';
|
|
1
3
|
import { Hono } from 'hono';
|
|
2
|
-
import { Config, ConfigActionExecuteRequest as ConfigActionExecuteRequest$1, ConfigActionExecuteResult as ConfigActionExecuteResult$1 } from '@nextclaw/core';
|
|
3
4
|
|
|
4
5
|
type ApiError = {
|
|
5
6
|
code: string;
|
|
@@ -85,6 +86,55 @@ type SessionPatchUpdate = {
|
|
|
85
86
|
preferredModel?: string | null;
|
|
86
87
|
clearHistory?: boolean;
|
|
87
88
|
};
|
|
89
|
+
type CronScheduleView = {
|
|
90
|
+
kind: "at";
|
|
91
|
+
atMs?: number | null;
|
|
92
|
+
} | {
|
|
93
|
+
kind: "every";
|
|
94
|
+
everyMs?: number | null;
|
|
95
|
+
} | {
|
|
96
|
+
kind: "cron";
|
|
97
|
+
expr?: string | null;
|
|
98
|
+
tz?: string | null;
|
|
99
|
+
};
|
|
100
|
+
type CronPayloadView = {
|
|
101
|
+
kind?: "system_event" | "agent_turn";
|
|
102
|
+
message: string;
|
|
103
|
+
deliver?: boolean;
|
|
104
|
+
channel?: string | null;
|
|
105
|
+
to?: string | null;
|
|
106
|
+
};
|
|
107
|
+
type CronJobStateView = {
|
|
108
|
+
nextRunAt?: string | null;
|
|
109
|
+
lastRunAt?: string | null;
|
|
110
|
+
lastStatus?: "ok" | "error" | "skipped" | null;
|
|
111
|
+
lastError?: string | null;
|
|
112
|
+
};
|
|
113
|
+
type CronJobView = {
|
|
114
|
+
id: string;
|
|
115
|
+
name: string;
|
|
116
|
+
enabled: boolean;
|
|
117
|
+
schedule: CronScheduleView;
|
|
118
|
+
payload: CronPayloadView;
|
|
119
|
+
state: CronJobStateView;
|
|
120
|
+
createdAt: string;
|
|
121
|
+
updatedAt: string;
|
|
122
|
+
deleteAfterRun: boolean;
|
|
123
|
+
};
|
|
124
|
+
type CronListView = {
|
|
125
|
+
jobs: CronJobView[];
|
|
126
|
+
total: number;
|
|
127
|
+
};
|
|
128
|
+
type CronEnableRequest = {
|
|
129
|
+
enabled: boolean;
|
|
130
|
+
};
|
|
131
|
+
type CronRunRequest = {
|
|
132
|
+
force?: boolean;
|
|
133
|
+
};
|
|
134
|
+
type CronActionResult = {
|
|
135
|
+
job: CronJobView | null;
|
|
136
|
+
executed?: boolean;
|
|
137
|
+
};
|
|
88
138
|
type RuntimeConfigUpdate = {
|
|
89
139
|
agents?: {
|
|
90
140
|
defaults?: {
|
|
@@ -363,6 +413,7 @@ type UiServerOptions = {
|
|
|
363
413
|
corsOrigins?: string[] | "*";
|
|
364
414
|
staticDir?: string;
|
|
365
415
|
marketplace?: MarketplaceApiConfig;
|
|
416
|
+
cronService?: CronService;
|
|
366
417
|
};
|
|
367
418
|
type UiServerHandle = {
|
|
368
419
|
host: string;
|
|
@@ -377,6 +428,7 @@ type UiRouterOptions = {
|
|
|
377
428
|
configPath: string;
|
|
378
429
|
publish: (event: UiServerEvent) => void;
|
|
379
430
|
marketplace?: MarketplaceApiConfig;
|
|
431
|
+
cronService?: InstanceType<typeof NextclawCore.CronService>;
|
|
380
432
|
};
|
|
381
433
|
declare function createUiRouter(options: UiRouterOptions): Hono;
|
|
382
434
|
|
|
@@ -410,4 +462,4 @@ declare function patchSession(configPath: string, key: string, patch: SessionPat
|
|
|
410
462
|
declare function deleteSession(configPath: string, key: string): boolean;
|
|
411
463
|
declare function updateRuntime(configPath: string, patch: RuntimeConfigUpdate): Pick<ConfigView, "agents" | "bindings" | "session">;
|
|
412
464
|
|
|
413
|
-
export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, type ConfigActionExecuteRequest, type ConfigActionExecuteResult, type ConfigActionManifest, type ConfigActionType, type ConfigMetaView, type ConfigSchemaResponse, type ConfigUiHint, type ConfigUiHints, type ConfigView, type MarketplaceApiConfig, type MarketplaceInstallKind, type MarketplaceInstallRequest, type MarketplaceInstallResult, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplaceManageAction, type MarketplaceManageRequest, type MarketplaceManageResult, type MarketplaceRecommendationView, type MarketplaceSort, type ProviderConfigUpdate, type ProviderConfigView, type ProviderSpecView, type RuntimeConfigUpdate, type SessionConfigView, type SessionEntryView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createUiRouter, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime };
|
|
465
|
+
export { type AgentBindingView, type AgentProfileView, type ApiError, type ApiResponse, type BindingPeerView, type ChannelSpecView, 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 MarketplaceInstallRequest, type MarketplaceInstallResult, type MarketplaceInstallSkillParams, type MarketplaceInstallSpec, type MarketplaceInstalledRecord, type MarketplaceInstalledView, type MarketplaceInstaller, type MarketplaceItemSummary, type MarketplaceItemType, type MarketplaceItemView, type MarketplaceListView, type MarketplaceManageAction, type MarketplaceManageRequest, type MarketplaceManageResult, type MarketplaceRecommendationView, type MarketplaceSort, type ProviderConfigUpdate, type ProviderConfigView, type ProviderSpecView, type RuntimeConfigUpdate, type SessionConfigView, type SessionEntryView, type SessionHistoryView, type SessionMessageView, type SessionPatchUpdate, type SessionsListView, type UiServerEvent, type UiServerHandle, type UiServerOptions, buildConfigMeta, buildConfigSchemaView, buildConfigView, createUiRouter, deleteSession, executeConfigAction, getSessionHistory, listSessions, loadConfigOrDefault, patchSession, startUiServer, updateChannel, updateModel, updateProvider, updateRuntime };
|
package/dist/index.js
CHANGED
|
@@ -691,6 +691,38 @@ function ok(data) {
|
|
|
691
691
|
function err(code, message, details) {
|
|
692
692
|
return { ok: false, error: { code, message, details } };
|
|
693
693
|
}
|
|
694
|
+
function toIsoTime(value) {
|
|
695
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
const date = new Date(value);
|
|
699
|
+
if (Number.isNaN(date.getTime())) {
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
return date.toISOString();
|
|
703
|
+
}
|
|
704
|
+
function buildCronJobView(job) {
|
|
705
|
+
return {
|
|
706
|
+
id: job.id,
|
|
707
|
+
name: job.name,
|
|
708
|
+
enabled: job.enabled,
|
|
709
|
+
schedule: job.schedule,
|
|
710
|
+
payload: job.payload,
|
|
711
|
+
state: {
|
|
712
|
+
nextRunAt: toIsoTime(job.state.nextRunAtMs),
|
|
713
|
+
lastRunAt: toIsoTime(job.state.lastRunAtMs),
|
|
714
|
+
lastStatus: job.state.lastStatus ?? null,
|
|
715
|
+
lastError: job.state.lastError ?? null
|
|
716
|
+
},
|
|
717
|
+
createdAt: new Date(job.createdAtMs).toISOString(),
|
|
718
|
+
updatedAt: new Date(job.updatedAtMs).toISOString(),
|
|
719
|
+
deleteAfterRun: job.deleteAfterRun
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
function findCronJob(service, id) {
|
|
723
|
+
const jobs = service.listJobs(true);
|
|
724
|
+
return jobs.find((job) => job.id === id) ?? null;
|
|
725
|
+
}
|
|
694
726
|
async function readJson(req) {
|
|
695
727
|
try {
|
|
696
728
|
const data = await req.json();
|
|
@@ -899,12 +931,13 @@ function collectMarketplaceInstalledView(options) {
|
|
|
899
931
|
records
|
|
900
932
|
};
|
|
901
933
|
}
|
|
902
|
-
function resolvePluginManageTargetId(options, rawTargetId) {
|
|
934
|
+
function resolvePluginManageTargetId(options, rawTargetId, rawSpec) {
|
|
903
935
|
const targetId = rawTargetId.trim();
|
|
904
|
-
if (!targetId) {
|
|
936
|
+
if (!targetId && !rawSpec) {
|
|
905
937
|
return rawTargetId;
|
|
906
938
|
}
|
|
907
|
-
const normalizedTarget = normalizePluginNpmSpec(targetId).toLowerCase();
|
|
939
|
+
const normalizedTarget = targetId ? normalizePluginNpmSpec(targetId).toLowerCase() : "";
|
|
940
|
+
const normalizedSpec = rawSpec ? normalizePluginNpmSpec(rawSpec).toLowerCase() : "";
|
|
908
941
|
const installed = collectMarketplaceInstalledView(options);
|
|
909
942
|
const pluginRecords = installed.records.filter((record) => record.type === "plugin");
|
|
910
943
|
const lowerTargetId = targetId.toLowerCase();
|
|
@@ -914,13 +947,23 @@ function resolvePluginManageTargetId(options, rawTargetId) {
|
|
|
914
947
|
return recordId;
|
|
915
948
|
}
|
|
916
949
|
}
|
|
917
|
-
|
|
918
|
-
const
|
|
919
|
-
|
|
920
|
-
|
|
950
|
+
if (normalizedTarget) {
|
|
951
|
+
for (const record of pluginRecords) {
|
|
952
|
+
const normalizedRecordSpec = normalizePluginNpmSpec(record.spec).toLowerCase();
|
|
953
|
+
if (normalizedRecordSpec === normalizedTarget && record.id && record.id.trim().length > 0) {
|
|
954
|
+
return record.id;
|
|
955
|
+
}
|
|
921
956
|
}
|
|
922
957
|
}
|
|
923
|
-
|
|
958
|
+
if (normalizedSpec && normalizedSpec !== normalizedTarget) {
|
|
959
|
+
for (const record of pluginRecords) {
|
|
960
|
+
const normalizedRecordSpec = normalizePluginNpmSpec(record.spec).toLowerCase();
|
|
961
|
+
if (normalizedRecordSpec === normalizedSpec && record.id && record.id.trim().length > 0) {
|
|
962
|
+
return record.id;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
return targetId || rawSpec || rawTargetId;
|
|
924
967
|
}
|
|
925
968
|
function sanitizeMarketplaceItem(item) {
|
|
926
969
|
const next = { ...item };
|
|
@@ -1022,7 +1065,8 @@ async function manageMarketplaceItem(params) {
|
|
|
1022
1065
|
const type = params.body.type;
|
|
1023
1066
|
const action = params.body.action;
|
|
1024
1067
|
const requestedTargetId = typeof params.body.id === "string" && params.body.id.trim().length > 0 ? params.body.id.trim() : typeof params.body.spec === "string" && params.body.spec.trim().length > 0 ? params.body.spec.trim() : "";
|
|
1025
|
-
const
|
|
1068
|
+
const rawSpec = typeof params.body.spec === "string" ? params.body.spec.trim() : "";
|
|
1069
|
+
const targetId = type === "plugin" ? resolvePluginManageTargetId(params.options, requestedTargetId, rawSpec) : requestedTargetId;
|
|
1026
1070
|
if (type !== "plugin" && type !== "skill" || action !== "enable" && action !== "disable" && action !== "uninstall" || !targetId) {
|
|
1027
1071
|
throw new Error("INVALID_BODY:type, action and non-empty id/spec are required");
|
|
1028
1072
|
}
|
|
@@ -1294,6 +1338,66 @@ function createUiRouter(options) {
|
|
|
1294
1338
|
options.publish({ type: "config.updated", payload: { path: "session" } });
|
|
1295
1339
|
return c.json(ok({ deleted: true }));
|
|
1296
1340
|
});
|
|
1341
|
+
app.get("/api/cron", (c) => {
|
|
1342
|
+
if (!options.cronService) {
|
|
1343
|
+
return c.json(err("NOT_AVAILABLE", "cron service unavailable"), 503);
|
|
1344
|
+
}
|
|
1345
|
+
const query = c.req.query();
|
|
1346
|
+
const includeDisabled = query.all === "1" || query.all === "true" || query.all === "yes";
|
|
1347
|
+
const jobs = options.cronService.listJobs(includeDisabled).map((job) => buildCronJobView(job));
|
|
1348
|
+
return c.json(ok({ jobs, total: jobs.length }));
|
|
1349
|
+
});
|
|
1350
|
+
app.delete("/api/cron/:id", (c) => {
|
|
1351
|
+
if (!options.cronService) {
|
|
1352
|
+
return c.json(err("NOT_AVAILABLE", "cron service unavailable"), 503);
|
|
1353
|
+
}
|
|
1354
|
+
const id = decodeURIComponent(c.req.param("id"));
|
|
1355
|
+
const deleted = options.cronService.removeJob(id);
|
|
1356
|
+
if (!deleted) {
|
|
1357
|
+
return c.json(err("NOT_FOUND", `cron job not found: ${id}`), 404);
|
|
1358
|
+
}
|
|
1359
|
+
return c.json(ok({ deleted: true }));
|
|
1360
|
+
});
|
|
1361
|
+
app.put("/api/cron/:id/enable", async (c) => {
|
|
1362
|
+
if (!options.cronService) {
|
|
1363
|
+
return c.json(err("NOT_AVAILABLE", "cron service unavailable"), 503);
|
|
1364
|
+
}
|
|
1365
|
+
const id = decodeURIComponent(c.req.param("id"));
|
|
1366
|
+
const body = await readJson(c.req.raw);
|
|
1367
|
+
if (!body.ok) {
|
|
1368
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
1369
|
+
}
|
|
1370
|
+
if (typeof body.data.enabled !== "boolean") {
|
|
1371
|
+
return c.json(err("INVALID_BODY", "enabled must be boolean"), 400);
|
|
1372
|
+
}
|
|
1373
|
+
const job = options.cronService.enableJob(id, body.data.enabled);
|
|
1374
|
+
if (!job) {
|
|
1375
|
+
return c.json(err("NOT_FOUND", `cron job not found: ${id}`), 404);
|
|
1376
|
+
}
|
|
1377
|
+
const data = { job: buildCronJobView(job) };
|
|
1378
|
+
return c.json(ok(data));
|
|
1379
|
+
});
|
|
1380
|
+
app.post("/api/cron/:id/run", async (c) => {
|
|
1381
|
+
if (!options.cronService) {
|
|
1382
|
+
return c.json(err("NOT_AVAILABLE", "cron service unavailable"), 503);
|
|
1383
|
+
}
|
|
1384
|
+
const id = decodeURIComponent(c.req.param("id"));
|
|
1385
|
+
const body = await readJson(c.req.raw);
|
|
1386
|
+
if (!body.ok) {
|
|
1387
|
+
return c.json(err("INVALID_BODY", "invalid json body"), 400);
|
|
1388
|
+
}
|
|
1389
|
+
const existing = findCronJob(options.cronService, id);
|
|
1390
|
+
if (!existing) {
|
|
1391
|
+
return c.json(err("NOT_FOUND", `cron job not found: ${id}`), 404);
|
|
1392
|
+
}
|
|
1393
|
+
const executed = await options.cronService.runJob(id, Boolean(body.data.force));
|
|
1394
|
+
const after = findCronJob(options.cronService, id);
|
|
1395
|
+
const data = {
|
|
1396
|
+
job: after ? buildCronJobView(after) : null,
|
|
1397
|
+
executed
|
|
1398
|
+
};
|
|
1399
|
+
return c.json(ok(data));
|
|
1400
|
+
});
|
|
1297
1401
|
app.put("/api/config/runtime", async (c) => {
|
|
1298
1402
|
const body = await readJson(c.req.raw);
|
|
1299
1403
|
if (!body.ok || !body.data || typeof body.data !== "object") {
|
|
@@ -1353,7 +1457,8 @@ function startUiServer(options) {
|
|
|
1353
1457
|
createUiRouter({
|
|
1354
1458
|
configPath: options.configPath,
|
|
1355
1459
|
publish,
|
|
1356
|
-
marketplace: options.marketplace
|
|
1460
|
+
marketplace: options.marketplace,
|
|
1461
|
+
cronService: options.cronService
|
|
1357
1462
|
})
|
|
1358
1463
|
);
|
|
1359
1464
|
const staticDir = options.staticDir;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
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.
|
|
18
|
+
"@nextclaw/openclaw-compat": "^0.1.23",
|
|
19
19
|
"hono": "^4.6.2",
|
|
20
20
|
"ws": "^8.18.0",
|
|
21
|
-
"@nextclaw/core": "^0.6.
|
|
21
|
+
"@nextclaw/core": "^0.6.30"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/node": "^20.17.6",
|