unraidclaw 0.1.2 → 0.1.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.js +124 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
|
+
import { request as httpsRequest, Agent as HttpsAgent } from "https";
|
|
3
|
+
import { request as httpRequest } from "http";
|
|
2
4
|
var UnraidApiError = class extends Error {
|
|
3
5
|
constructor(message, statusCode, errorCode) {
|
|
4
6
|
super(message);
|
|
@@ -9,7 +11,7 @@ var UnraidApiError = class extends Error {
|
|
|
9
11
|
};
|
|
10
12
|
var UnraidClient = class {
|
|
11
13
|
configResolver;
|
|
12
|
-
|
|
14
|
+
insecureAgent = null;
|
|
13
15
|
constructor(configResolver) {
|
|
14
16
|
this.configResolver = configResolver;
|
|
15
17
|
}
|
|
@@ -18,13 +20,13 @@ var UnraidClient = class {
|
|
|
18
20
|
if (!cfg.serverUrl) {
|
|
19
21
|
throw new UnraidApiError("UnraidClaw serverUrl not configured", 0, "CONFIG_ERROR");
|
|
20
22
|
}
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
this.tlsConfigured = true;
|
|
23
|
+
if (cfg.tlsSkipVerify && cfg.serverUrl.startsWith("https") && !this.insecureAgent) {
|
|
24
|
+
this.insecureAgent = new HttpsAgent({ rejectUnauthorized: false });
|
|
24
25
|
}
|
|
25
26
|
return {
|
|
26
27
|
baseUrl: cfg.serverUrl.replace(/\/+$/, ""),
|
|
27
|
-
apiKey: cfg.apiKey || ""
|
|
28
|
+
apiKey: cfg.apiKey || "",
|
|
29
|
+
isHttps: cfg.serverUrl.startsWith("https")
|
|
28
30
|
};
|
|
29
31
|
}
|
|
30
32
|
async get(path, query) {
|
|
@@ -34,49 +36,72 @@ var UnraidClient = class {
|
|
|
34
36
|
const params = new URLSearchParams(query);
|
|
35
37
|
url += `?${params.toString()}`;
|
|
36
38
|
}
|
|
37
|
-
return this.
|
|
39
|
+
return this.doRequest("GET", url);
|
|
38
40
|
}
|
|
39
41
|
async post(path, body) {
|
|
40
42
|
const { baseUrl } = this.getConfig();
|
|
41
|
-
return this.
|
|
43
|
+
return this.doRequest("POST", `${baseUrl}${path}`, body);
|
|
42
44
|
}
|
|
43
45
|
async patch(path, body) {
|
|
44
46
|
const { baseUrl } = this.getConfig();
|
|
45
|
-
return this.
|
|
47
|
+
return this.doRequest("PATCH", `${baseUrl}${path}`, body);
|
|
46
48
|
}
|
|
47
49
|
async delete(path) {
|
|
48
50
|
const { baseUrl } = this.getConfig();
|
|
49
|
-
return this.
|
|
51
|
+
return this.doRequest("DELETE", `${baseUrl}${path}`);
|
|
50
52
|
}
|
|
51
|
-
|
|
52
|
-
const { apiKey } = this.getConfig();
|
|
53
|
+
doRequest(method, url, body) {
|
|
54
|
+
const { apiKey, isHttps } = this.getConfig();
|
|
55
|
+
const parsed = new URL(url);
|
|
56
|
+
const payload = body !== void 0 ? JSON.stringify(body) : void 0;
|
|
53
57
|
const headers = {
|
|
54
58
|
"x-api-key": apiKey
|
|
55
59
|
};
|
|
56
|
-
|
|
57
|
-
if (body !== void 0) {
|
|
60
|
+
if (payload) {
|
|
58
61
|
headers["Content-Type"] = "application/json";
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
headers["Content-Length"] = Buffer.byteLength(payload).toString();
|
|
63
|
+
}
|
|
64
|
+
const requestFn = isHttps ? httpsRequest : httpRequest;
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const req = requestFn(
|
|
67
|
+
{
|
|
68
|
+
hostname: parsed.hostname,
|
|
69
|
+
port: parsed.port || (isHttps ? 443 : 80),
|
|
70
|
+
path: parsed.pathname + parsed.search,
|
|
71
|
+
method,
|
|
72
|
+
headers,
|
|
73
|
+
...this.insecureAgent ? { agent: this.insecureAgent } : {}
|
|
74
|
+
},
|
|
75
|
+
(res) => {
|
|
76
|
+
const chunks = [];
|
|
77
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
78
|
+
res.on("end", () => {
|
|
79
|
+
const text = Buffer.concat(chunks).toString();
|
|
80
|
+
let json;
|
|
81
|
+
try {
|
|
82
|
+
json = JSON.parse(text);
|
|
83
|
+
} catch {
|
|
84
|
+
reject(new UnraidApiError(`Invalid JSON response: ${text.slice(0, 200)}`, res.statusCode ?? 0, "PARSE_ERROR"));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!json.ok) {
|
|
88
|
+
reject(new UnraidApiError(json.error.message, res.statusCode ?? 0, json.error.code));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
resolve(json.data);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
77
94
|
);
|
|
78
|
-
|
|
79
|
-
|
|
95
|
+
req.on("error", (err) => {
|
|
96
|
+
reject(new UnraidApiError(
|
|
97
|
+
`Connection failed: ${err.message}`,
|
|
98
|
+
0,
|
|
99
|
+
"CONNECTION_ERROR"
|
|
100
|
+
));
|
|
101
|
+
});
|
|
102
|
+
if (payload) req.write(payload);
|
|
103
|
+
req.end();
|
|
104
|
+
});
|
|
80
105
|
}
|
|
81
106
|
};
|
|
82
107
|
|
|
@@ -94,7 +119,7 @@ function registerHealthTools(api, client) {
|
|
|
94
119
|
api.registerTool({
|
|
95
120
|
name: "unraid_health_check",
|
|
96
121
|
description: "Check the health status of the Unraid server connection, including API and GraphQL reachability.",
|
|
97
|
-
parameters: { type: "object" },
|
|
122
|
+
parameters: { type: "object", properties: {} },
|
|
98
123
|
execute: async () => {
|
|
99
124
|
try {
|
|
100
125
|
return textResult(await client.get("/api/health"));
|
|
@@ -110,7 +135,7 @@ function registerDockerTools(api, client) {
|
|
|
110
135
|
api.registerTool({
|
|
111
136
|
name: "unraid_docker_list",
|
|
112
137
|
description: "List all Docker containers on the Unraid server with their current state, image, and status.",
|
|
113
|
-
parameters: { type: "object" },
|
|
138
|
+
parameters: { type: "object", properties: {} },
|
|
114
139
|
execute: async () => {
|
|
115
140
|
try {
|
|
116
141
|
return textResult(await client.get("/api/docker/containers"));
|
|
@@ -252,17 +277,59 @@ function registerDockerTools(api, client) {
|
|
|
252
277
|
});
|
|
253
278
|
api.registerTool({
|
|
254
279
|
name: "unraid_docker_remove",
|
|
255
|
-
description: "Remove a Docker container. This is a destructive operation that cannot be undone.",
|
|
280
|
+
description: "Remove a Docker container. Pass force=true to stop and remove in one step. This is a destructive operation that cannot be undone.",
|
|
256
281
|
parameters: {
|
|
257
282
|
type: "object",
|
|
258
283
|
properties: {
|
|
259
|
-
id: { type: "string", description: "Container ID or name" }
|
|
284
|
+
id: { type: "string", description: "Container ID or name" },
|
|
285
|
+
force: { type: "boolean", description: "Stop the container before removing (default: false)" }
|
|
260
286
|
},
|
|
261
287
|
required: ["id"]
|
|
262
288
|
},
|
|
263
289
|
execute: async (_id, params) => {
|
|
264
290
|
try {
|
|
265
|
-
|
|
291
|
+
const query = params.force ? "?force=true" : "";
|
|
292
|
+
return textResult(await client.delete(`/api/docker/containers/${params.id}${query}`));
|
|
293
|
+
} catch (err) {
|
|
294
|
+
return errorResult(err);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
api.registerTool({
|
|
299
|
+
name: "unraid_docker_create",
|
|
300
|
+
description: "Create and start a new Docker container on the Unraid server. Specify image, optional name, port mappings, volume mounts, environment variables, restart policy, and network.",
|
|
301
|
+
parameters: {
|
|
302
|
+
type: "object",
|
|
303
|
+
properties: {
|
|
304
|
+
image: { type: "string", description: "Docker image to use (e.g. vikunja/vikunja:latest)" },
|
|
305
|
+
name: { type: "string", description: "Optional container name" },
|
|
306
|
+
ports: {
|
|
307
|
+
type: "array",
|
|
308
|
+
items: { type: "string" },
|
|
309
|
+
description: "Port mappings in host:container format (e.g. ['3456:3456'])"
|
|
310
|
+
},
|
|
311
|
+
volumes: {
|
|
312
|
+
type: "array",
|
|
313
|
+
items: { type: "string" },
|
|
314
|
+
description: "Volume mounts in host:container format (e.g. ['/mnt/cache/appdata/vikunja:/app/vikunja'])"
|
|
315
|
+
},
|
|
316
|
+
env: {
|
|
317
|
+
type: "array",
|
|
318
|
+
items: { type: "string" },
|
|
319
|
+
description: "Environment variables in KEY=VALUE format"
|
|
320
|
+
},
|
|
321
|
+
restart: {
|
|
322
|
+
type: "string",
|
|
323
|
+
enum: ["no", "always", "unless-stopped", "on-failure"],
|
|
324
|
+
description: "Restart policy (default: unless-stopped)"
|
|
325
|
+
},
|
|
326
|
+
network: { type: "string", description: "Network to attach the container to" }
|
|
327
|
+
},
|
|
328
|
+
required: ["image"]
|
|
329
|
+
},
|
|
330
|
+
execute: async (_id, params) => {
|
|
331
|
+
try {
|
|
332
|
+
return textResult(await client.post("/api/docker/containers", params));
|
|
266
333
|
} catch (err) {
|
|
267
334
|
return errorResult(err);
|
|
268
335
|
}
|
|
@@ -275,7 +342,7 @@ function registerVMTools(api, client) {
|
|
|
275
342
|
api.registerTool({
|
|
276
343
|
name: "unraid_vm_list",
|
|
277
344
|
description: "List all virtual machines on the Unraid server with their current state.",
|
|
278
|
-
parameters: { type: "object" },
|
|
345
|
+
parameters: { type: "object", properties: {} },
|
|
279
346
|
execute: async () => {
|
|
280
347
|
try {
|
|
281
348
|
return textResult(await client.get("/api/vms"));
|
|
@@ -419,7 +486,7 @@ function registerArrayTools(api, client) {
|
|
|
419
486
|
api.registerTool({
|
|
420
487
|
name: "unraid_array_status",
|
|
421
488
|
description: "Get the current status of the Unraid array including state, capacity, disks, and parities. Capacity is in kilobytes (KiB). Disk 'size' fields are in kilobytes (KiB).",
|
|
422
|
-
parameters: { type: "object" },
|
|
489
|
+
parameters: { type: "object", properties: {} },
|
|
423
490
|
execute: async () => {
|
|
424
491
|
try {
|
|
425
492
|
return textResult(await client.get("/api/array/status"));
|
|
@@ -431,7 +498,7 @@ function registerArrayTools(api, client) {
|
|
|
431
498
|
api.registerTool({
|
|
432
499
|
name: "unraid_array_start",
|
|
433
500
|
description: "Start the Unraid array. This will mount all disks and start Docker/VMs if configured.",
|
|
434
|
-
parameters: { type: "object" },
|
|
501
|
+
parameters: { type: "object", properties: {} },
|
|
435
502
|
execute: async () => {
|
|
436
503
|
try {
|
|
437
504
|
return textResult(await client.post("/api/array/start"));
|
|
@@ -443,7 +510,7 @@ function registerArrayTools(api, client) {
|
|
|
443
510
|
api.registerTool({
|
|
444
511
|
name: "unraid_array_stop",
|
|
445
512
|
description: "Stop the Unraid array. This will stop all Docker containers and VMs, then unmount all disks.",
|
|
446
|
-
parameters: { type: "object" },
|
|
513
|
+
parameters: { type: "object", properties: {} },
|
|
447
514
|
execute: async () => {
|
|
448
515
|
try {
|
|
449
516
|
return textResult(await client.post("/api/array/stop"));
|
|
@@ -455,7 +522,7 @@ function registerArrayTools(api, client) {
|
|
|
455
522
|
api.registerTool({
|
|
456
523
|
name: "unraid_parity_status",
|
|
457
524
|
description: "Get the current parity check status (running, progress, speed, errors).",
|
|
458
|
-
parameters: { type: "object" },
|
|
525
|
+
parameters: { type: "object", properties: {} },
|
|
459
526
|
execute: async () => {
|
|
460
527
|
try {
|
|
461
528
|
return textResult(await client.get("/api/array/parity/status"));
|
|
@@ -487,7 +554,7 @@ function registerArrayTools(api, client) {
|
|
|
487
554
|
api.registerTool({
|
|
488
555
|
name: "unraid_parity_pause",
|
|
489
556
|
description: "Pause a running parity check.",
|
|
490
|
-
parameters: { type: "object" },
|
|
557
|
+
parameters: { type: "object", properties: {} },
|
|
491
558
|
execute: async () => {
|
|
492
559
|
try {
|
|
493
560
|
return textResult(await client.post("/api/array/parity/pause"));
|
|
@@ -499,7 +566,7 @@ function registerArrayTools(api, client) {
|
|
|
499
566
|
api.registerTool({
|
|
500
567
|
name: "unraid_parity_resume",
|
|
501
568
|
description: "Resume a paused parity check.",
|
|
502
|
-
parameters: { type: "object" },
|
|
569
|
+
parameters: { type: "object", properties: {} },
|
|
503
570
|
execute: async () => {
|
|
504
571
|
try {
|
|
505
572
|
return textResult(await client.post("/api/array/parity/resume"));
|
|
@@ -511,7 +578,7 @@ function registerArrayTools(api, client) {
|
|
|
511
578
|
api.registerTool({
|
|
512
579
|
name: "unraid_parity_cancel",
|
|
513
580
|
description: "Cancel a running or paused parity check.",
|
|
514
|
-
parameters: { type: "object" },
|
|
581
|
+
parameters: { type: "object", properties: {} },
|
|
515
582
|
execute: async () => {
|
|
516
583
|
try {
|
|
517
584
|
return textResult(await client.post("/api/array/parity/cancel"));
|
|
@@ -527,7 +594,7 @@ function registerDiskTools(api, client) {
|
|
|
527
594
|
api.registerTool({
|
|
528
595
|
name: "unraid_disk_list",
|
|
529
596
|
description: "List all disks in the Unraid server with basic info (name, size, temp, status). The 'size' field is in kilobytes (KiB).",
|
|
530
|
-
parameters: { type: "object" },
|
|
597
|
+
parameters: { type: "object", properties: {} },
|
|
531
598
|
execute: async () => {
|
|
532
599
|
try {
|
|
533
600
|
return textResult(await client.get("/api/disks"));
|
|
@@ -561,7 +628,7 @@ function registerShareTools(api, client) {
|
|
|
561
628
|
api.registerTool({
|
|
562
629
|
name: "unraid_share_list",
|
|
563
630
|
description: "List all user shares on the Unraid server with their settings and usage. The 'free' and 'size' fields are in kilobytes (KiB).",
|
|
564
|
-
parameters: { type: "object" },
|
|
631
|
+
parameters: { type: "object", properties: {} },
|
|
565
632
|
execute: async () => {
|
|
566
633
|
try {
|
|
567
634
|
return textResult(await client.get("/api/shares"));
|
|
@@ -618,7 +685,7 @@ function registerSystemTools(api, client) {
|
|
|
618
685
|
api.registerTool({
|
|
619
686
|
name: "unraid_system_info",
|
|
620
687
|
description: "Get system information including OS, CPU, memory, and Unraid/kernel versions.",
|
|
621
|
-
parameters: { type: "object" },
|
|
688
|
+
parameters: { type: "object", properties: {} },
|
|
622
689
|
execute: async () => {
|
|
623
690
|
try {
|
|
624
691
|
return textResult(await client.get("/api/system/info"));
|
|
@@ -630,7 +697,7 @@ function registerSystemTools(api, client) {
|
|
|
630
697
|
api.registerTool({
|
|
631
698
|
name: "unraid_system_metrics",
|
|
632
699
|
description: "Get live system metrics: CPU usage, memory usage, load average, and uptime.",
|
|
633
|
-
parameters: { type: "object" },
|
|
700
|
+
parameters: { type: "object", properties: {} },
|
|
634
701
|
execute: async () => {
|
|
635
702
|
try {
|
|
636
703
|
return textResult(await client.get("/api/system/metrics"));
|
|
@@ -642,7 +709,7 @@ function registerSystemTools(api, client) {
|
|
|
642
709
|
api.registerTool({
|
|
643
710
|
name: "unraid_service_list",
|
|
644
711
|
description: "List system services and their current state.",
|
|
645
|
-
parameters: { type: "object" },
|
|
712
|
+
parameters: { type: "object", properties: {} },
|
|
646
713
|
execute: async () => {
|
|
647
714
|
try {
|
|
648
715
|
return textResult(await client.get("/api/system/services"));
|
|
@@ -654,7 +721,7 @@ function registerSystemTools(api, client) {
|
|
|
654
721
|
api.registerTool({
|
|
655
722
|
name: "unraid_system_reboot",
|
|
656
723
|
description: "Reboot the Unraid server. This is a destructive operation that will interrupt all running services, VMs, and containers.",
|
|
657
|
-
parameters: { type: "object" },
|
|
724
|
+
parameters: { type: "object", properties: {} },
|
|
658
725
|
execute: async () => {
|
|
659
726
|
try {
|
|
660
727
|
return textResult(await client.post("/api/system/reboot"));
|
|
@@ -666,7 +733,7 @@ function registerSystemTools(api, client) {
|
|
|
666
733
|
api.registerTool({
|
|
667
734
|
name: "unraid_system_shutdown",
|
|
668
735
|
description: "Shut down the Unraid server. This is a destructive operation that will power off the server.",
|
|
669
|
-
parameters: { type: "object" },
|
|
736
|
+
parameters: { type: "object", properties: {} },
|
|
670
737
|
execute: async () => {
|
|
671
738
|
try {
|
|
672
739
|
return textResult(await client.post("/api/system/shutdown"));
|
|
@@ -682,7 +749,7 @@ function registerNotificationTools(api, client) {
|
|
|
682
749
|
api.registerTool({
|
|
683
750
|
name: "unraid_notification_list",
|
|
684
751
|
description: "List all system notifications with their importance level and archive status.",
|
|
685
|
-
parameters: { type: "object" },
|
|
752
|
+
parameters: { type: "object", properties: {} },
|
|
686
753
|
execute: async () => {
|
|
687
754
|
try {
|
|
688
755
|
return textResult(await client.get("/api/notifications"));
|
|
@@ -761,7 +828,7 @@ function registerNetworkTools(api, client) {
|
|
|
761
828
|
api.registerTool({
|
|
762
829
|
name: "unraid_network_info",
|
|
763
830
|
description: "Get network information including hostname, gateway, DNS servers, and all network interfaces.",
|
|
764
|
-
parameters: { type: "object" },
|
|
831
|
+
parameters: { type: "object", properties: {} },
|
|
765
832
|
execute: async () => {
|
|
766
833
|
try {
|
|
767
834
|
return textResult(await client.get("/api/network"));
|
|
@@ -777,7 +844,7 @@ function registerUserTools(api, client) {
|
|
|
777
844
|
api.registerTool({
|
|
778
845
|
name: "unraid_user_me",
|
|
779
846
|
description: "Get information about the current authenticated user.",
|
|
780
|
-
parameters: { type: "object" },
|
|
847
|
+
parameters: { type: "object", properties: {} },
|
|
781
848
|
execute: async () => {
|
|
782
849
|
try {
|
|
783
850
|
return textResult(await client.get("/api/users/me"));
|
|
@@ -837,7 +904,7 @@ function register(api) {
|
|
|
837
904
|
registerUserTools(api, client);
|
|
838
905
|
registerLogTools(api, client);
|
|
839
906
|
const cfg = resolveConfig(api);
|
|
840
|
-
log.info(`UnraidClaw: registered
|
|
907
|
+
log.info(`UnraidClaw: registered 40 tools${cfg.serverUrl ? ", server: " + cfg.serverUrl : " (config will resolve at runtime)"}`);
|
|
841
908
|
}
|
|
842
909
|
export {
|
|
843
910
|
register as default
|