@coffeexdev/openclaw-sentinel 0.1.4 → 0.1.5
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/tool.js +2 -8
- package/dist/toolSchema.d.ts +34 -0
- package/dist/toolSchema.js +77 -0
- package/package.json +2 -1
package/dist/tool.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsonResult } from "openclaw/plugin-sdk";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { SentinelToolSchema } from "./toolSchema.js";
|
|
3
4
|
const ParamsSchema = z
|
|
4
5
|
.object({
|
|
5
6
|
action: z.enum(["create", "enable", "disable", "remove", "status", "list"]),
|
|
@@ -12,14 +13,7 @@ export function registerSentinelControl(registerTool, manager) {
|
|
|
12
13
|
name: "sentinel_control",
|
|
13
14
|
label: "sentinel_control",
|
|
14
15
|
description: "Create/manage sentinel watchers",
|
|
15
|
-
parameters:
|
|
16
|
-
action: {
|
|
17
|
-
type: "string",
|
|
18
|
-
enum: ["create", "enable", "disable", "remove", "status", "list"],
|
|
19
|
-
},
|
|
20
|
-
id: { type: "string" },
|
|
21
|
-
watcher: { type: "object" },
|
|
22
|
-
},
|
|
16
|
+
parameters: SentinelToolSchema,
|
|
23
17
|
async execute(_toolCallId, params) {
|
|
24
18
|
const payload = ParamsSchema.parse((params ?? {}));
|
|
25
19
|
switch (payload.action) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const SentinelToolSchema: import("@sinclair/typebox").TObject<{
|
|
2
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"create">, import("@sinclair/typebox").TLiteral<"enable">, import("@sinclair/typebox").TLiteral<"disable">, import("@sinclair/typebox").TLiteral<"remove">, import("@sinclair/typebox").TLiteral<"status">, import("@sinclair/typebox").TLiteral<"list">]>;
|
|
3
|
+
id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
4
|
+
watcher: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
5
|
+
id: import("@sinclair/typebox").TString;
|
|
6
|
+
skillId: import("@sinclair/typebox").TString;
|
|
7
|
+
enabled: import("@sinclair/typebox").TBoolean;
|
|
8
|
+
strategy: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"http-poll">, import("@sinclair/typebox").TLiteral<"websocket">, import("@sinclair/typebox").TLiteral<"sse">, import("@sinclair/typebox").TLiteral<"http-long-poll">]>;
|
|
9
|
+
endpoint: import("@sinclair/typebox").TString;
|
|
10
|
+
method: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"GET">, import("@sinclair/typebox").TLiteral<"POST">]>>;
|
|
11
|
+
headers: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>>;
|
|
12
|
+
body: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
13
|
+
intervalMs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
14
|
+
timeoutMs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
15
|
+
match: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"all">, import("@sinclair/typebox").TLiteral<"any">]>;
|
|
16
|
+
conditions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
17
|
+
path: import("@sinclair/typebox").TString;
|
|
18
|
+
op: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"eq">, import("@sinclair/typebox").TLiteral<"neq">, import("@sinclair/typebox").TLiteral<"gt">, import("@sinclair/typebox").TLiteral<"gte">, import("@sinclair/typebox").TLiteral<"lt">, import("@sinclair/typebox").TLiteral<"lte">, import("@sinclair/typebox").TLiteral<"exists">, import("@sinclair/typebox").TLiteral<"absent">, import("@sinclair/typebox").TLiteral<"contains">, import("@sinclair/typebox").TLiteral<"matches">, import("@sinclair/typebox").TLiteral<"changed">]>;
|
|
19
|
+
value: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
|
|
20
|
+
}>>;
|
|
21
|
+
fire: import("@sinclair/typebox").TObject<{
|
|
22
|
+
webhookPath: import("@sinclair/typebox").TString;
|
|
23
|
+
eventName: import("@sinclair/typebox").TString;
|
|
24
|
+
payloadTemplate: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TBoolean, import("@sinclair/typebox").TNull]>>;
|
|
25
|
+
}>;
|
|
26
|
+
retry: import("@sinclair/typebox").TObject<{
|
|
27
|
+
maxRetries: import("@sinclair/typebox").TNumber;
|
|
28
|
+
baseMs: import("@sinclair/typebox").TNumber;
|
|
29
|
+
maxMs: import("@sinclair/typebox").TNumber;
|
|
30
|
+
}>;
|
|
31
|
+
fireOnce: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
32
|
+
metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>>;
|
|
33
|
+
}>>;
|
|
34
|
+
}>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
const ConditionSchema = Type.Object({
|
|
3
|
+
path: Type.String({ description: "JSONPath expression to evaluate against the response" }),
|
|
4
|
+
op: Type.Union([
|
|
5
|
+
Type.Literal("eq"),
|
|
6
|
+
Type.Literal("neq"),
|
|
7
|
+
Type.Literal("gt"),
|
|
8
|
+
Type.Literal("gte"),
|
|
9
|
+
Type.Literal("lt"),
|
|
10
|
+
Type.Literal("lte"),
|
|
11
|
+
Type.Literal("exists"),
|
|
12
|
+
Type.Literal("absent"),
|
|
13
|
+
Type.Literal("contains"),
|
|
14
|
+
Type.Literal("matches"),
|
|
15
|
+
Type.Literal("changed"),
|
|
16
|
+
], { description: "Comparison operator" }),
|
|
17
|
+
value: Type.Optional(Type.Unknown({
|
|
18
|
+
description: "Value to compare against (not needed for exists/absent/changed)",
|
|
19
|
+
})),
|
|
20
|
+
});
|
|
21
|
+
const FireConfigSchema = Type.Object({
|
|
22
|
+
webhookPath: Type.String({
|
|
23
|
+
description: "Path appended to localDispatchBase for webhook delivery",
|
|
24
|
+
}),
|
|
25
|
+
eventName: Type.String({ description: "Event name included in the dispatched payload" }),
|
|
26
|
+
payloadTemplate: Type.Record(Type.String(), Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]), {
|
|
27
|
+
description: "Key-value template for the webhook payload. Supports {{mustache}} interpolation from matched response data.",
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
const RetryPolicySchema = Type.Object({
|
|
31
|
+
maxRetries: Type.Number({ description: "Maximum number of retry attempts" }),
|
|
32
|
+
baseMs: Type.Number({ description: "Base delay in milliseconds for exponential backoff" }),
|
|
33
|
+
maxMs: Type.Number({ description: "Maximum delay cap in milliseconds" }),
|
|
34
|
+
});
|
|
35
|
+
const WatcherSchema = Type.Object({
|
|
36
|
+
id: Type.String({ description: "Unique watcher identifier" }),
|
|
37
|
+
skillId: Type.String({ description: "ID of the skill that owns this watcher" }),
|
|
38
|
+
enabled: Type.Boolean({ description: "Whether the watcher is actively polling" }),
|
|
39
|
+
strategy: Type.Union([
|
|
40
|
+
Type.Literal("http-poll"),
|
|
41
|
+
Type.Literal("websocket"),
|
|
42
|
+
Type.Literal("sse"),
|
|
43
|
+
Type.Literal("http-long-poll"),
|
|
44
|
+
], { description: "Connection strategy" }),
|
|
45
|
+
endpoint: Type.String({ description: "URL to monitor" }),
|
|
46
|
+
method: Type.Optional(Type.Union([Type.Literal("GET"), Type.Literal("POST")], {
|
|
47
|
+
description: "HTTP method (default GET)",
|
|
48
|
+
})),
|
|
49
|
+
headers: Type.Optional(Type.Record(Type.String(), Type.String(), {
|
|
50
|
+
description: "HTTP headers to include in requests",
|
|
51
|
+
})),
|
|
52
|
+
body: Type.Optional(Type.String({ description: "Request body for POST requests" })),
|
|
53
|
+
intervalMs: Type.Optional(Type.Number({ description: "Polling interval in milliseconds" })),
|
|
54
|
+
timeoutMs: Type.Optional(Type.Number({ description: "Request timeout in milliseconds" })),
|
|
55
|
+
match: Type.Union([Type.Literal("all"), Type.Literal("any")], {
|
|
56
|
+
description: "Whether all or any conditions must match to trigger",
|
|
57
|
+
}),
|
|
58
|
+
conditions: Type.Array(ConditionSchema, {
|
|
59
|
+
description: "Conditions evaluated against each response",
|
|
60
|
+
}),
|
|
61
|
+
fire: FireConfigSchema,
|
|
62
|
+
retry: RetryPolicySchema,
|
|
63
|
+
fireOnce: Type.Optional(Type.Boolean({ description: "If true, the watcher disables itself after firing once" })),
|
|
64
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.String(), { description: "Arbitrary key-value metadata" })),
|
|
65
|
+
}, { description: "Full watcher definition" });
|
|
66
|
+
export const SentinelToolSchema = Type.Object({
|
|
67
|
+
action: Type.Union([
|
|
68
|
+
Type.Literal("create"),
|
|
69
|
+
Type.Literal("enable"),
|
|
70
|
+
Type.Literal("disable"),
|
|
71
|
+
Type.Literal("remove"),
|
|
72
|
+
Type.Literal("status"),
|
|
73
|
+
Type.Literal("list"),
|
|
74
|
+
], { description: "The action to perform" }),
|
|
75
|
+
id: Type.Optional(Type.String({ description: "Watcher ID (required for enable/disable/remove/status)" })),
|
|
76
|
+
watcher: Type.Optional(WatcherSchema),
|
|
77
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffeexdev/openclaw-sentinel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Secure declarative gateway-native watcher plugin for OpenClaw",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openclaw",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"prepare": "husky"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
+
"@sinclair/typebox": "^0.34.48",
|
|
45
46
|
"re2-wasm": "^1.0.2",
|
|
46
47
|
"ws": "^8.18.3",
|
|
47
48
|
"zod": "^3.24.1"
|