@coffeexdev/openclaw-sentinel 0.4.1 → 0.4.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/README.md +1 -1
- package/dist/tool.d.ts +2 -2
- package/dist/tool.js +13 -7
- package/dist/toolSchema.d.ts +52 -4
- package/dist/toolSchema.js +44 -12
- package/dist/validator.d.ts +2 -2
- package/dist/validator.js +11 -5
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -132,7 +132,7 @@ It **does not** execute user-authored code from watcher definitions.
|
|
|
132
132
|
## Features
|
|
133
133
|
|
|
134
134
|
- Tool registration: `sentinel_control`
|
|
135
|
-
- actions: `create
|
|
135
|
+
- actions: `create` (`add`), `enable`, `disable`, `remove` (`delete`), `status` (`get`), `list`
|
|
136
136
|
- Strict schema validation (TypeBox, strict object checks) + code-like field/value rejection
|
|
137
137
|
- Strategies:
|
|
138
138
|
- `http-poll`
|
package/dist/tool.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AnyAgentTool } from "openclaw/plugin-sdk";
|
|
2
2
|
import type { Static } from "@sinclair/typebox";
|
|
3
3
|
import { WatcherManager } from "./watcherManager.js";
|
|
4
|
-
import {
|
|
5
|
-
export type SentinelToolParams = Static<typeof
|
|
4
|
+
import { SentinelToolValidationSchema } from "./toolSchema.js";
|
|
5
|
+
export type SentinelToolParams = Static<typeof SentinelToolValidationSchema>;
|
|
6
6
|
type SentinelToolContext = {
|
|
7
7
|
messageChannel?: string;
|
|
8
8
|
requesterSenderId?: string;
|
package/dist/tool.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { jsonResult } from "openclaw/plugin-sdk";
|
|
2
2
|
import { Value } from "@sinclair/typebox/value";
|
|
3
|
-
import { SentinelToolSchema } from "./toolSchema.js";
|
|
3
|
+
import { SentinelToolSchema, SentinelToolValidationSchema } from "./toolSchema.js";
|
|
4
|
+
import { TemplateValueSchema } from "./templateValueSchema.js";
|
|
4
5
|
function validateParams(params) {
|
|
5
6
|
const candidate = (params ?? {});
|
|
6
|
-
if (!Value.Check(
|
|
7
|
-
const first = [
|
|
7
|
+
if (!Value.Check(SentinelToolValidationSchema, [TemplateValueSchema], candidate)) {
|
|
8
|
+
const first = [
|
|
9
|
+
...Value.Errors(SentinelToolValidationSchema, [TemplateValueSchema], candidate),
|
|
10
|
+
][0];
|
|
8
11
|
const where = first?.path || "(root)";
|
|
9
12
|
const why = first?.message || "Invalid parameters";
|
|
10
13
|
throw new Error(`Invalid sentinel_control parameters at ${where}: ${why}`);
|
|
@@ -35,17 +38,20 @@ export function registerSentinelControl(registerTool, manager) {
|
|
|
35
38
|
const payload = validateParams(params);
|
|
36
39
|
switch (payload.action) {
|
|
37
40
|
case "create":
|
|
41
|
+
case "add":
|
|
38
42
|
return jsonResult(await manager.create(payload.watcher, {
|
|
39
43
|
deliveryTargets: inferDefaultDeliveryTargets(ctx),
|
|
40
44
|
}));
|
|
41
45
|
case "enable":
|
|
42
|
-
return jsonResult(await manager.enable(payload.id
|
|
46
|
+
return jsonResult(await manager.enable(payload.id));
|
|
43
47
|
case "disable":
|
|
44
|
-
return jsonResult(await manager.disable(payload.id
|
|
48
|
+
return jsonResult(await manager.disable(payload.id));
|
|
45
49
|
case "remove":
|
|
46
|
-
|
|
50
|
+
case "delete":
|
|
51
|
+
return jsonResult(await manager.remove(payload.id));
|
|
47
52
|
case "status":
|
|
48
|
-
|
|
53
|
+
case "get":
|
|
54
|
+
return jsonResult(manager.status(payload.id));
|
|
49
55
|
case "list":
|
|
50
56
|
return jsonResult(manager.list());
|
|
51
57
|
}
|
package/dist/toolSchema.d.ts
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
|
+
export declare const SentinelToolValidationSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
2
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"create">, import("@sinclair/typebox").TLiteral<"add">]>;
|
|
3
|
+
watcher: import("@sinclair/typebox").TObject<{
|
|
4
|
+
id: import("@sinclair/typebox").TString;
|
|
5
|
+
skillId: import("@sinclair/typebox").TString;
|
|
6
|
+
enabled: import("@sinclair/typebox").TBoolean;
|
|
7
|
+
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">]>;
|
|
8
|
+
endpoint: import("@sinclair/typebox").TString;
|
|
9
|
+
method: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"GET">, import("@sinclair/typebox").TLiteral<"POST">]>>;
|
|
10
|
+
headers: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>>;
|
|
11
|
+
body: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
12
|
+
intervalMs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
13
|
+
timeoutMs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
14
|
+
match: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"all">, import("@sinclair/typebox").TLiteral<"any">]>;
|
|
15
|
+
conditions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
16
|
+
path: import("@sinclair/typebox").TString;
|
|
17
|
+
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">]>;
|
|
18
|
+
value: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
|
|
19
|
+
}>>;
|
|
20
|
+
fire: import("@sinclair/typebox").TObject<{
|
|
21
|
+
webhookPath: import("@sinclair/typebox").TString;
|
|
22
|
+
eventName: import("@sinclair/typebox").TString;
|
|
23
|
+
payloadTemplate: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TRef<any>>;
|
|
24
|
+
intent: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
25
|
+
contextTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TRef<any>>>;
|
|
26
|
+
priority: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"low">, import("@sinclair/typebox").TLiteral<"normal">, import("@sinclair/typebox").TLiteral<"high">, import("@sinclair/typebox").TLiteral<"critical">]>>;
|
|
27
|
+
deadlineTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
28
|
+
dedupeKeyTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
29
|
+
}>;
|
|
30
|
+
retry: import("@sinclair/typebox").TObject<{
|
|
31
|
+
maxRetries: import("@sinclair/typebox").TNumber;
|
|
32
|
+
baseMs: import("@sinclair/typebox").TNumber;
|
|
33
|
+
maxMs: import("@sinclair/typebox").TNumber;
|
|
34
|
+
}>;
|
|
35
|
+
fireOnce: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
36
|
+
deliveryTargets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
37
|
+
channel: import("@sinclair/typebox").TString;
|
|
38
|
+
to: import("@sinclair/typebox").TString;
|
|
39
|
+
accountId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
40
|
+
}>>>;
|
|
41
|
+
metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>>;
|
|
42
|
+
}>;
|
|
43
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
44
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"enable">, import("@sinclair/typebox").TLiteral<"disable">, import("@sinclair/typebox").TLiteral<"remove">, import("@sinclair/typebox").TLiteral<"delete">, import("@sinclair/typebox").TLiteral<"status">, import("@sinclair/typebox").TLiteral<"get">]>;
|
|
45
|
+
id: import("@sinclair/typebox").TString;
|
|
46
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
47
|
+
action: import("@sinclair/typebox").TLiteral<"list">;
|
|
48
|
+
}>]>;
|
|
1
49
|
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>;
|
|
50
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"create">, import("@sinclair/typebox").TLiteral<"add">]>, import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"enable">, import("@sinclair/typebox").TLiteral<"disable">, import("@sinclair/typebox").TLiteral<"remove">, import("@sinclair/typebox").TLiteral<"delete">, import("@sinclair/typebox").TLiteral<"status">, import("@sinclair/typebox").TLiteral<"get">]>, import("@sinclair/typebox").TLiteral<"list">]>;
|
|
4
51
|
watcher: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
5
52
|
id: import("@sinclair/typebox").TString;
|
|
6
53
|
skillId: import("@sinclair/typebox").TString;
|
|
@@ -21,9 +68,9 @@ export declare const SentinelToolSchema: import("@sinclair/typebox").TObject<{
|
|
|
21
68
|
fire: import("@sinclair/typebox").TObject<{
|
|
22
69
|
webhookPath: import("@sinclair/typebox").TString;
|
|
23
70
|
eventName: import("@sinclair/typebox").TString;
|
|
24
|
-
payloadTemplate: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, any
|
|
71
|
+
payloadTemplate: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TRef<any>>;
|
|
25
72
|
intent: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
26
|
-
contextTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, any
|
|
73
|
+
contextTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TRef<any>>>;
|
|
27
74
|
priority: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"low">, import("@sinclair/typebox").TLiteral<"normal">, import("@sinclair/typebox").TLiteral<"high">, import("@sinclair/typebox").TLiteral<"critical">]>>;
|
|
28
75
|
deadlineTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
29
76
|
dedupeKeyTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
@@ -41,4 +88,5 @@ export declare const SentinelToolSchema: import("@sinclair/typebox").TObject<{
|
|
|
41
88
|
}>>>;
|
|
42
89
|
metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>>;
|
|
43
90
|
}>>;
|
|
91
|
+
id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
44
92
|
}>;
|
package/dist/toolSchema.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import { TemplateValueSchema } from "./templateValueSchema.js";
|
|
3
|
+
const TemplateValueRefSchema = Type.Ref(TemplateValueSchema);
|
|
3
4
|
const ConditionSchema = Type.Object({
|
|
4
5
|
path: Type.String({ description: "JSONPath expression to evaluate against the response" }),
|
|
5
6
|
op: Type.Union([
|
|
@@ -24,11 +25,11 @@ const FireConfigSchema = Type.Object({
|
|
|
24
25
|
description: "Path appended to localDispatchBase for webhook delivery",
|
|
25
26
|
}),
|
|
26
27
|
eventName: Type.String({ description: "Event name included in the dispatched payload" }),
|
|
27
|
-
payloadTemplate: Type.Record(Type.String(),
|
|
28
|
+
payloadTemplate: Type.Record(Type.String(), TemplateValueRefSchema, {
|
|
28
29
|
description: "Key-value template for the webhook payload. Supports ${...} interpolation from matched response data.",
|
|
29
30
|
}),
|
|
30
31
|
intent: Type.Optional(Type.String({ description: "Generic callback intent for downstream agent routing" })),
|
|
31
|
-
contextTemplate: Type.Optional(Type.Record(Type.String(),
|
|
32
|
+
contextTemplate: Type.Optional(Type.Record(Type.String(), TemplateValueRefSchema, {
|
|
32
33
|
description: "Structured callback context template. Supports ${...} interpolation from matched response data.",
|
|
33
34
|
})),
|
|
34
35
|
priority: Type.Optional(Type.Union([Type.Literal("low"), Type.Literal("normal"), Type.Literal("high"), Type.Literal("critical")], { description: "Callback urgency hint" })),
|
|
@@ -79,15 +80,46 @@ const WatcherSchema = Type.Object({
|
|
|
79
80
|
})),
|
|
80
81
|
metadata: Type.Optional(Type.Record(Type.String(), Type.String(), { description: "Arbitrary key-value metadata" })),
|
|
81
82
|
}, { description: "Full watcher definition" });
|
|
83
|
+
const CreateActionNameSchema = Type.Union([Type.Literal("create"), Type.Literal("add")], {
|
|
84
|
+
description: "Create action (alias: add)",
|
|
85
|
+
});
|
|
86
|
+
const IdActionNameSchema = Type.Union([
|
|
87
|
+
Type.Literal("enable"),
|
|
88
|
+
Type.Literal("disable"),
|
|
89
|
+
Type.Literal("remove"),
|
|
90
|
+
Type.Literal("delete"),
|
|
91
|
+
Type.Literal("status"),
|
|
92
|
+
Type.Literal("get"),
|
|
93
|
+
], { description: "ID-targeting action aliases: delete/remove and get/status" });
|
|
94
|
+
const ListActionNameSchema = Type.Literal("list", { description: "List all watchers" });
|
|
95
|
+
const AnyActionNameSchema = Type.Union([
|
|
96
|
+
CreateActionNameSchema,
|
|
97
|
+
IdActionNameSchema,
|
|
98
|
+
ListActionNameSchema,
|
|
99
|
+
]);
|
|
100
|
+
const CreateActionSchema = Type.Object({
|
|
101
|
+
action: CreateActionNameSchema,
|
|
102
|
+
watcher: WatcherSchema,
|
|
103
|
+
}, { additionalProperties: false });
|
|
104
|
+
const IdActionSchema = Type.Object({
|
|
105
|
+
action: IdActionNameSchema,
|
|
106
|
+
id: Type.String({ description: "Watcher ID for action target" }),
|
|
107
|
+
}, { additionalProperties: false });
|
|
108
|
+
const ListActionSchema = Type.Object({
|
|
109
|
+
action: ListActionNameSchema,
|
|
110
|
+
}, { additionalProperties: false });
|
|
111
|
+
export const SentinelToolValidationSchema = Type.Union([CreateActionSchema, IdActionSchema, ListActionSchema], {
|
|
112
|
+
$defs: {
|
|
113
|
+
templateValue: TemplateValueSchema,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
82
116
|
export const SentinelToolSchema = Type.Object({
|
|
83
|
-
action:
|
|
84
|
-
Type.Literal("create"),
|
|
85
|
-
Type.Literal("enable"),
|
|
86
|
-
Type.Literal("disable"),
|
|
87
|
-
Type.Literal("remove"),
|
|
88
|
-
Type.Literal("status"),
|
|
89
|
-
Type.Literal("list"),
|
|
90
|
-
], { description: "The action to perform" }),
|
|
91
|
-
id: Type.Optional(Type.String({ description: "Watcher ID (required for enable/disable/remove/status)" })),
|
|
117
|
+
action: AnyActionNameSchema,
|
|
92
118
|
watcher: Type.Optional(WatcherSchema),
|
|
93
|
-
|
|
119
|
+
id: Type.Optional(Type.String({ description: "Watcher ID for action target" })),
|
|
120
|
+
}, {
|
|
121
|
+
additionalProperties: false,
|
|
122
|
+
$defs: {
|
|
123
|
+
templateValue: TemplateValueSchema,
|
|
124
|
+
},
|
|
125
|
+
});
|
package/dist/validator.d.ts
CHANGED
|
@@ -19,9 +19,9 @@ export declare const WatcherSchema: import("@sinclair/typebox").TObject<{
|
|
|
19
19
|
fire: import("@sinclair/typebox").TObject<{
|
|
20
20
|
webhookPath: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
21
21
|
eventName: import("@sinclair/typebox").TString;
|
|
22
|
-
payloadTemplate: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, any
|
|
22
|
+
payloadTemplate: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TRef<any>>;
|
|
23
23
|
intent: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
24
|
-
contextTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, any
|
|
24
|
+
contextTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TRef<any>>>;
|
|
25
25
|
priority: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"low">, import("@sinclair/typebox").TLiteral<"normal">, import("@sinclair/typebox").TLiteral<"high">, import("@sinclair/typebox").TLiteral<"critical">]>>;
|
|
26
26
|
deadlineTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
27
27
|
dedupeKeyTemplate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
package/dist/validator.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Type } from "@sinclair/typebox";
|
|
|
2
2
|
import { Value } from "@sinclair/typebox/value";
|
|
3
3
|
import { TemplateValueSchema } from "./templateValueSchema.js";
|
|
4
4
|
import { DEFAULT_SENTINEL_WEBHOOK_PATH } from "./types.js";
|
|
5
|
+
const TemplateValueRefSchema = Type.Ref(TemplateValueSchema);
|
|
5
6
|
const codeyKeyPattern = /(script|code|eval|handler|function|import|require)/i;
|
|
6
7
|
const codeyValuePattern = /(=>|\bfunction\b|\bimport\s+|\brequire\s*\(|\beval\s*\()/i;
|
|
7
8
|
const ConditionSchema = Type.Object({
|
|
@@ -42,9 +43,9 @@ export const WatcherSchema = Type.Object({
|
|
|
42
43
|
fire: Type.Object({
|
|
43
44
|
webhookPath: Type.Optional(Type.String({ pattern: "^/" })),
|
|
44
45
|
eventName: Type.String({ minLength: 1 }),
|
|
45
|
-
payloadTemplate: Type.Record(Type.String(),
|
|
46
|
+
payloadTemplate: Type.Record(Type.String(), TemplateValueRefSchema),
|
|
46
47
|
intent: Type.Optional(Type.String({ minLength: 1 })),
|
|
47
|
-
contextTemplate: Type.Optional(Type.Record(Type.String(),
|
|
48
|
+
contextTemplate: Type.Optional(Type.Record(Type.String(), TemplateValueRefSchema)),
|
|
48
49
|
priority: Type.Optional(Type.Union([
|
|
49
50
|
Type.Literal("low"),
|
|
50
51
|
Type.Literal("normal"),
|
|
@@ -66,7 +67,12 @@ export const WatcherSchema = Type.Object({
|
|
|
66
67
|
accountId: Type.Optional(Type.String({ minLength: 1 })),
|
|
67
68
|
}, { additionalProperties: false }), { minItems: 1 })),
|
|
68
69
|
metadata: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
69
|
-
}, {
|
|
70
|
+
}, {
|
|
71
|
+
additionalProperties: false,
|
|
72
|
+
$defs: {
|
|
73
|
+
templateValue: TemplateValueSchema,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
70
76
|
function scanNoCodeLike(input, parentKey = "") {
|
|
71
77
|
if (input === null || input === undefined)
|
|
72
78
|
return;
|
|
@@ -91,8 +97,8 @@ function scanNoCodeLike(input, parentKey = "") {
|
|
|
91
97
|
}
|
|
92
98
|
export function validateWatcherDefinition(input) {
|
|
93
99
|
scanNoCodeLike(input);
|
|
94
|
-
if (!Value.Check(WatcherSchema, input)) {
|
|
95
|
-
const first = [...Value.Errors(WatcherSchema, input)][0];
|
|
100
|
+
if (!Value.Check(WatcherSchema, [TemplateValueSchema], input)) {
|
|
101
|
+
const first = [...Value.Errors(WatcherSchema, [TemplateValueSchema], input)][0];
|
|
96
102
|
const where = first?.path || "(root)";
|
|
97
103
|
const why = first?.message || "Invalid watcher definition";
|
|
98
104
|
throw new Error(`Invalid watcher definition at ${where}: ${why}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffeexdev/openclaw-sentinel",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Secure declarative gateway-native watcher plugin for OpenClaw",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openclaw",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"@changesets/cli": "^2.29.7",
|
|
39
39
|
"@types/node": "^24.0.0",
|
|
40
40
|
"@types/ws": "^8.5.13",
|
|
41
|
+
"ajv": "^8.17.1",
|
|
41
42
|
"husky": "^9.1.7",
|
|
42
43
|
"lint-staged": "^16.3.2",
|
|
43
44
|
"openclaw": "latest",
|