@clawnitor/plugin 1.0.0
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 +60 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -0
- package/dist/event-builder.d.ts +15 -0
- package/dist/event-builder.d.ts.map +1 -0
- package/dist/event-builder.js +34 -0
- package/dist/event-builder.js.map +1 -0
- package/dist/hooks/lifecycle.d.ts +18 -0
- package/dist/hooks/lifecycle.d.ts.map +1 -0
- package/dist/hooks/lifecycle.js +79 -0
- package/dist/hooks/lifecycle.js.map +1 -0
- package/dist/hooks/llm.d.ts +11 -0
- package/dist/hooks/llm.d.ts.map +1 -0
- package/dist/hooks/llm.js +35 -0
- package/dist/hooks/llm.js.map +1 -0
- package/dist/hooks/message.d.ts +14 -0
- package/dist/hooks/message.d.ts.map +1 -0
- package/dist/hooks/message.js +52 -0
- package/dist/hooks/message.js.map +1 -0
- package/dist/hooks/tool-call.d.ts +20 -0
- package/dist/hooks/tool-call.d.ts.map +1 -0
- package/dist/hooks/tool-call.js +89 -0
- package/dist/hooks/tool-call.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/dist/kill-switch/kill-state.d.ts +16 -0
- package/dist/kill-switch/kill-state.d.ts.map +1 -0
- package/dist/kill-switch/kill-state.js +25 -0
- package/dist/kill-switch/kill-state.js.map +1 -0
- package/dist/kill-switch/local-failsafe.d.ts +19 -0
- package/dist/kill-switch/local-failsafe.d.ts.map +1 -0
- package/dist/kill-switch/local-failsafe.js +64 -0
- package/dist/kill-switch/local-failsafe.js.map +1 -0
- package/dist/redaction.d.ts +3 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +46 -0
- package/dist/redaction.js.map +1 -0
- package/dist/rule-cache.d.ts +42 -0
- package/dist/rule-cache.d.ts.map +1 -0
- package/dist/rule-cache.js +138 -0
- package/dist/rule-cache.js.map +1 -0
- package/dist/severity.d.ts +8 -0
- package/dist/severity.d.ts.map +1 -0
- package/dist/severity.js +38 -0
- package/dist/severity.js.map +1 -0
- package/dist/transport/https-sender.d.ts +18 -0
- package/dist/transport/https-sender.d.ts.map +1 -0
- package/dist/transport/https-sender.js +62 -0
- package/dist/transport/https-sender.js.map +1 -0
- package/dist/transport/sqlite-cache.d.ts +12 -0
- package/dist/transport/sqlite-cache.d.ts.map +1 -0
- package/dist/transport/sqlite-cache.js +74 -0
- package/dist/transport/sqlite-cache.js.map +1 -0
- package/dist/transport/websocket-client.d.ts +19 -0
- package/dist/transport/websocket-client.d.ts.map +1 -0
- package/dist/transport/websocket-client.js +79 -0
- package/dist/transport/websocket-client.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @clawnitor/plugin
|
|
2
|
+
|
|
3
|
+
OpenClaw plugin for Clawnitor — agent monitoring, alerting, and kill switch.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
openclaw plugins install @clawnitor/plugin
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Add to your `openclaw.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"plugins": {
|
|
18
|
+
"entries": {
|
|
19
|
+
"clawnitor": {
|
|
20
|
+
"config": {
|
|
21
|
+
"apiKey": "clw_live_your_key_here"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Options
|
|
30
|
+
|
|
31
|
+
| Option | Default | Description |
|
|
32
|
+
|--------|---------|-------------|
|
|
33
|
+
| `apiKey` | required | Your Clawnitor API key |
|
|
34
|
+
| `backendUrl` | `https://api.clawnitor.io` | Backend URL |
|
|
35
|
+
| `spendLimit` | `100` | Max spend per session ($) before auto-pause |
|
|
36
|
+
| `rateLimit` | `120` | Max tool calls per minute before auto-pause |
|
|
37
|
+
| `toolBlocklist` | `[]` | Tool names to always block |
|
|
38
|
+
| `redactionPatterns` | `[]` | Additional regex patterns for secret redaction |
|
|
39
|
+
|
|
40
|
+
## What it monitors
|
|
41
|
+
|
|
42
|
+
- Tool calls (before and after execution)
|
|
43
|
+
- LLM requests (input/output, token usage, cost)
|
|
44
|
+
- Messages (sending, sent, received)
|
|
45
|
+
- Session lifecycle (start, end, agent completion)
|
|
46
|
+
- Sub-agent spawning and completion
|
|
47
|
+
|
|
48
|
+
## Safety features
|
|
49
|
+
|
|
50
|
+
- **Kill switch** — blocks tool calls and messages when agent is paused (server or local)
|
|
51
|
+
- **Spend circuit breaker** — auto-pauses at configurable spend limit
|
|
52
|
+
- **Rate limiter** — auto-pauses at configurable tool call rate
|
|
53
|
+
- **Tool blocklist** — prevents specific tools from ever executing
|
|
54
|
+
- **Secret redaction** — strips API keys, passwords, tokens from logged data
|
|
55
|
+
|
|
56
|
+
## Privacy
|
|
57
|
+
|
|
58
|
+
Event data streams to the Clawnitor backend for monitoring. Sensitive data (API keys, passwords, tokens) is automatically redacted before transmission. Data sharing for aggregate pattern improvement is opt-in (default OFF).
|
|
59
|
+
|
|
60
|
+
Learn more at https://clawnitor.io
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface PluginConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
backendUrl: string;
|
|
4
|
+
spendLimit: number;
|
|
5
|
+
rateLimit: number;
|
|
6
|
+
toolBlocklist: string[];
|
|
7
|
+
redactionPatterns: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function parseConfig(raw: Record<string, unknown>): PluginConfig;
|
|
10
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CActE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DEFAULT_SPEND_LIMIT, DEFAULT_RATE_LIMIT, } from "@clawnitor/shared";
|
|
2
|
+
export function parseConfig(raw) {
|
|
3
|
+
const apiKey = raw.apiKey;
|
|
4
|
+
if (!apiKey) {
|
|
5
|
+
throw new Error("Clawnitor: apiKey is required. Sign up at https://clawnitor.io");
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
apiKey,
|
|
9
|
+
backendUrl: raw.backendUrl || "https://api.clawnitor.io",
|
|
10
|
+
spendLimit: raw.spendLimit ?? DEFAULT_SPEND_LIMIT,
|
|
11
|
+
rateLimit: raw.rateLimit ?? DEFAULT_RATE_LIMIT,
|
|
12
|
+
toolBlocklist: raw.toolBlocklist ?? [],
|
|
13
|
+
redactionPatterns: raw.redactionPatterns ?? [],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAW3B,MAAM,UAAU,WAAW,CAAC,GAA4B;IACtD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAgB,CAAC;IACpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IAED,OAAO;QACL,MAAM;QACN,UAAU,EAAG,GAAG,CAAC,UAAqB,IAAI,0BAA0B;QACpE,UAAU,EAAG,GAAG,CAAC,UAAqB,IAAI,mBAAmB;QAC7D,SAAS,EAAG,GAAG,CAAC,SAAoB,IAAI,kBAAkB;QAC1D,aAAa,EAAG,GAAG,CAAC,aAA0B,IAAI,EAAE;QACpD,iBAAiB,EAAG,GAAG,CAAC,iBAA8B,IAAI,EAAE;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ClawnitorEvent, type EventType } from "@clawnitor/shared";
|
|
2
|
+
import { type RateTracker } from "./severity.js";
|
|
3
|
+
interface BuildEventParams {
|
|
4
|
+
agentId: string;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
eventType: EventType;
|
|
7
|
+
action: string;
|
|
8
|
+
target: string;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
rateTracker?: RateTracker;
|
|
11
|
+
customRedactionPatterns?: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare function buildEvent(params: BuildEventParams): ClawnitorEvent;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=event-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-builder.d.ts","sourceRoot":"","sources":["../src/event-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,SAAS,EAAqB,MAAM,mBAAmB,CAAC;AAC1G,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAKjE,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;CACpC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,cAAc,CA6CnE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createEventId } from "@clawnitor/shared";
|
|
2
|
+
import { assignSeverity } from "./severity.js";
|
|
3
|
+
import { redact, DEFAULT_PATTERNS } from "./redaction.js";
|
|
4
|
+
const PLUGIN_VERSION = "0.0.1";
|
|
5
|
+
export function buildEvent(params) {
|
|
6
|
+
const { agentId, sessionId, eventType, action, target, metadata = {}, rateTracker, customRedactionPatterns = [], } = params;
|
|
7
|
+
// Redact sensitive data from raw_snippet
|
|
8
|
+
const patterns = [...DEFAULT_PATTERNS, ...customRedactionPatterns];
|
|
9
|
+
const cleaned = { ...metadata };
|
|
10
|
+
if (typeof cleaned.raw_snippet === "string") {
|
|
11
|
+
cleaned.raw_snippet = redact(cleaned.raw_snippet, patterns);
|
|
12
|
+
// Truncate to 500 chars
|
|
13
|
+
if (cleaned.raw_snippet.length > 500) {
|
|
14
|
+
cleaned.raw_snippet = cleaned.raw_snippet.slice(0, 500);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const severity = assignSeverity(eventType, cleaned, rateTracker);
|
|
18
|
+
// Redact action and target fields too
|
|
19
|
+
const redactedAction = redact(action, patterns);
|
|
20
|
+
const redactedTarget = redact(target, patterns);
|
|
21
|
+
return {
|
|
22
|
+
agent_id: agentId,
|
|
23
|
+
session_id: sessionId,
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
event_type: eventType,
|
|
26
|
+
action: redactedAction,
|
|
27
|
+
target: redactedTarget,
|
|
28
|
+
metadata: cleaned,
|
|
29
|
+
severity_hint: severity,
|
|
30
|
+
event_id: createEventId(),
|
|
31
|
+
plugin_version: PLUGIN_VERSION,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=event-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-builder.js","sourceRoot":"","sources":["../src/event-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA0D,MAAM,mBAAmB,CAAC;AAC1G,OAAO,EAAE,cAAc,EAAoB,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,MAAM,cAAc,GAAG,OAAO,CAAC;AAa/B,MAAM,UAAU,UAAU,CAAC,MAAwB;IACjD,MAAM,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,MAAM,EACN,QAAQ,GAAG,EAAE,EACb,WAAW,EACX,uBAAuB,GAAG,EAAE,GAC7B,GAAG,MAAM,CAAC;IAEX,yCAAyC;IACzC,MAAM,QAAQ,GAAG,CAAC,GAAG,gBAAgB,EAAE,GAAG,uBAAuB,CAAC,CAAC;IACnE,MAAM,OAAO,GAA4B,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzD,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC5D,wBAAwB;QACxB,IAAK,OAAO,CAAC,WAAsB,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACjD,OAAO,CAAC,WAAW,GAAI,OAAO,CAAC,WAAsB,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,cAAc,CAC7B,SAAS,EACT,OAAO,EACP,WAAW,CACZ,CAAC;IAEF,sCAAsC;IACtC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChD,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEhD,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,UAAU,EAAE,SAAS;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,cAAc;QACtB,MAAM,EAAE,cAAc;QACtB,QAAQ,EAAE,OAAc;QACxB,aAAa,EAAE,QAAQ;QACvB,QAAQ,EAAE,aAAa,EAAE;QACzB,cAAc,EAAE,cAAc;KAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HttpsSender } from "../transport/https-sender.js";
|
|
2
|
+
interface LifecycleContext {
|
|
3
|
+
agentId: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
sender: HttpsSender;
|
|
6
|
+
redactionPatterns: string[];
|
|
7
|
+
onSessionStart?: (sessionId: string) => void;
|
|
8
|
+
onSessionEnd?: (sessionId: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createSessionStartHandler(ctx: LifecycleContext): (event: any) => void;
|
|
11
|
+
export declare function createSessionEndHandler(ctx: LifecycleContext): (event: any) => void;
|
|
12
|
+
export declare function createAgentEndHandler(ctx: LifecycleContext): (event: any) => void;
|
|
13
|
+
export declare function createSubagentHandlers(ctx: LifecycleContext): {
|
|
14
|
+
spawning: (event: any) => void;
|
|
15
|
+
ended: (event: any) => void;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/hooks/lifecycle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhE,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,gBAAgB,IACrD,OAAO,GAAG,UAenB;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,IACnD,OAAO,GAAG,UAiBnB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,IACjD,OAAO,GAAG,UAgBnB;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB;sBAEtC,GAAG;mBAYN,GAAG;EAarB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { buildEvent } from "../event-builder.js";
|
|
2
|
+
export function createSessionStartHandler(ctx) {
|
|
3
|
+
return (event) => {
|
|
4
|
+
ctx.onSessionStart?.(event.sessionId || ctx.sessionId);
|
|
5
|
+
const clawnitorEvent = buildEvent({
|
|
6
|
+
agentId: ctx.agentId,
|
|
7
|
+
sessionId: event.sessionId || ctx.sessionId,
|
|
8
|
+
eventType: "agent_lifecycle",
|
|
9
|
+
action: "session started",
|
|
10
|
+
target: "session",
|
|
11
|
+
metadata: {},
|
|
12
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
13
|
+
});
|
|
14
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function createSessionEndHandler(ctx) {
|
|
18
|
+
return (event) => {
|
|
19
|
+
ctx.onSessionEnd?.(event.sessionId || ctx.sessionId);
|
|
20
|
+
const clawnitorEvent = buildEvent({
|
|
21
|
+
agentId: ctx.agentId,
|
|
22
|
+
sessionId: event.sessionId || ctx.sessionId,
|
|
23
|
+
eventType: "agent_lifecycle",
|
|
24
|
+
action: "session ended",
|
|
25
|
+
target: "session",
|
|
26
|
+
metadata: {
|
|
27
|
+
duration_ms: event.duration,
|
|
28
|
+
},
|
|
29
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
30
|
+
});
|
|
31
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function createAgentEndHandler(ctx) {
|
|
35
|
+
return (event) => {
|
|
36
|
+
const clawnitorEvent = buildEvent({
|
|
37
|
+
agentId: ctx.agentId,
|
|
38
|
+
sessionId: ctx.sessionId,
|
|
39
|
+
eventType: "agent_lifecycle",
|
|
40
|
+
action: event.error ? "agent ended with error" : "agent ended",
|
|
41
|
+
target: "agent",
|
|
42
|
+
metadata: {
|
|
43
|
+
duration_ms: event.duration,
|
|
44
|
+
error: event.error?.message,
|
|
45
|
+
},
|
|
46
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
47
|
+
});
|
|
48
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function createSubagentHandlers(ctx) {
|
|
52
|
+
return {
|
|
53
|
+
spawning: (event) => {
|
|
54
|
+
const clawnitorEvent = buildEvent({
|
|
55
|
+
agentId: ctx.agentId,
|
|
56
|
+
sessionId: ctx.sessionId,
|
|
57
|
+
eventType: "subagent",
|
|
58
|
+
action: "subagent spawning",
|
|
59
|
+
target: event.subagentId || "unknown",
|
|
60
|
+
metadata: {},
|
|
61
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
62
|
+
});
|
|
63
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
64
|
+
},
|
|
65
|
+
ended: (event) => {
|
|
66
|
+
const clawnitorEvent = buildEvent({
|
|
67
|
+
agentId: ctx.agentId,
|
|
68
|
+
sessionId: ctx.sessionId,
|
|
69
|
+
eventType: "subagent",
|
|
70
|
+
action: "subagent ended",
|
|
71
|
+
target: event.subagentId || "unknown",
|
|
72
|
+
metadata: { duration_ms: event.duration },
|
|
73
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
74
|
+
});
|
|
75
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/hooks/lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HttpsSender } from "../transport/https-sender.js";
|
|
2
|
+
interface LlmContext {
|
|
3
|
+
agentId: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
sender: HttpsSender;
|
|
6
|
+
redactionPatterns: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function createLlmInputHandler(ctx: LlmContext): (event: any) => void;
|
|
9
|
+
export declare function createLlmOutputHandler(ctx: LlmContext): (event: any) => void;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/hooks/llm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhE,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,IAC3C,OAAO,GAAG,UAenB;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,UAAU,IAC5C,OAAO,GAAG,UAgBnB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { buildEvent } from "../event-builder.js";
|
|
2
|
+
export function createLlmInputHandler(ctx) {
|
|
3
|
+
return (event) => {
|
|
4
|
+
const clawnitorEvent = buildEvent({
|
|
5
|
+
agentId: ctx.agentId,
|
|
6
|
+
sessionId: ctx.sessionId,
|
|
7
|
+
eventType: "llm_call",
|
|
8
|
+
action: `llm_input: ${event.model || "unknown"}`,
|
|
9
|
+
target: event.provider || "unknown",
|
|
10
|
+
metadata: {
|
|
11
|
+
tool_name: event.model,
|
|
12
|
+
},
|
|
13
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
14
|
+
});
|
|
15
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function createLlmOutputHandler(ctx) {
|
|
19
|
+
return (event) => {
|
|
20
|
+
const clawnitorEvent = buildEvent({
|
|
21
|
+
agentId: ctx.agentId,
|
|
22
|
+
sessionId: ctx.sessionId,
|
|
23
|
+
eventType: "llm_call",
|
|
24
|
+
action: `llm_output: ${event.model || "unknown"}`,
|
|
25
|
+
target: event.provider || "unknown",
|
|
26
|
+
metadata: {
|
|
27
|
+
tokens_used: event.usage?.totalTokens,
|
|
28
|
+
cost_usd: event.usage?.cost,
|
|
29
|
+
},
|
|
30
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
31
|
+
});
|
|
32
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/hooks/llm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAUjD,MAAM,UAAU,qBAAqB,CAAC,GAAe;IACnD,OAAO,CAAC,KAAU,EAAE,EAAE;QACpB,MAAM,cAAc,GAAG,UAAU,CAAC;YAChC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,cAAc,KAAK,CAAC,KAAK,IAAI,SAAS,EAAE;YAChD,MAAM,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS;YACnC,QAAQ,EAAE;gBACR,SAAS,EAAE,KAAK,CAAC,KAAK;aACvB;YACD,uBAAuB,EAAE,GAAG,CAAC,iBAAiB;SAC/C,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,GAAe;IACpD,OAAO,CAAC,KAAU,EAAE,EAAE;QACpB,MAAM,cAAc,GAAG,UAAU,CAAC;YAChC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,eAAe,KAAK,CAAC,KAAK,IAAI,SAAS,EAAE;YACjD,MAAM,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS;YACnC,QAAQ,EAAE;gBACR,WAAW,EAAE,KAAK,CAAC,KAAK,EAAE,WAAW;gBACrC,QAAQ,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI;aAC5B;YACD,uBAAuB,EAAE,GAAG,CAAC,iBAAiB;SAC/C,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { HttpsSender } from "../transport/https-sender.js";
|
|
2
|
+
interface MessageContext {
|
|
3
|
+
agentId: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
sender: HttpsSender;
|
|
6
|
+
redactionPatterns: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function createMessageSendingHandler(ctx: MessageContext): (event: any) => {
|
|
9
|
+
cancel: boolean;
|
|
10
|
+
} | undefined;
|
|
11
|
+
export declare function createMessageSentHandler(ctx: MessageContext): (event: any) => void;
|
|
12
|
+
export declare function createMessageReceivedHandler(ctx: MessageContext): (event: any) => void;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/hooks/message.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGhE,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,cAAc,IACrD,OAAO,GAAG;;cAsBnB;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,cAAc,IAClD,OAAO,GAAG,UAanB;AAED,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,cAAc,IACtD,OAAO,GAAG,UAanB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { buildEvent } from "../event-builder.js";
|
|
2
|
+
import { killState } from "../kill-switch/kill-state.js";
|
|
3
|
+
export function createMessageSendingHandler(ctx) {
|
|
4
|
+
return (event) => {
|
|
5
|
+
const clawnitorEvent = buildEvent({
|
|
6
|
+
agentId: ctx.agentId,
|
|
7
|
+
sessionId: ctx.sessionId,
|
|
8
|
+
eventType: "message_sent",
|
|
9
|
+
action: `sending message`,
|
|
10
|
+
target: event.channel || "unknown",
|
|
11
|
+
metadata: {
|
|
12
|
+
raw_snippet: event.text ? String(event.text).slice(0, 500) : undefined,
|
|
13
|
+
},
|
|
14
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
15
|
+
});
|
|
16
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
17
|
+
// Block outbound messages when killed
|
|
18
|
+
if (killState.isKilled()) {
|
|
19
|
+
return { cancel: true };
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function createMessageSentHandler(ctx) {
|
|
25
|
+
return (event) => {
|
|
26
|
+
const clawnitorEvent = buildEvent({
|
|
27
|
+
agentId: ctx.agentId,
|
|
28
|
+
sessionId: ctx.sessionId,
|
|
29
|
+
eventType: "message_sent",
|
|
30
|
+
action: `message sent`,
|
|
31
|
+
target: event.channel || "unknown",
|
|
32
|
+
metadata: {},
|
|
33
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
34
|
+
});
|
|
35
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function createMessageReceivedHandler(ctx) {
|
|
39
|
+
return (event) => {
|
|
40
|
+
const clawnitorEvent = buildEvent({
|
|
41
|
+
agentId: ctx.agentId,
|
|
42
|
+
sessionId: ctx.sessionId,
|
|
43
|
+
eventType: "message_received",
|
|
44
|
+
action: `message received`,
|
|
45
|
+
target: event.channel || "unknown",
|
|
46
|
+
metadata: {},
|
|
47
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
48
|
+
});
|
|
49
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/hooks/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AASzD,MAAM,UAAU,2BAA2B,CAAC,GAAmB;IAC7D,OAAO,CAAC,KAAU,EAAE,EAAE;QACpB,MAAM,cAAc,GAAG,UAAU,CAAC;YAChC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,cAAc;YACzB,MAAM,EAAE,iBAAiB;YACzB,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,SAAS;YAClC,QAAQ,EAAE;gBACR,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;aACvE;YACD,uBAAuB,EAAE,GAAG,CAAC,iBAAiB;SAC/C,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEnC,sCAAsC;QACtC,IAAI,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;YACzB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,GAAmB;IAC1D,OAAO,CAAC,KAAU,EAAE,EAAE;QACpB,MAAM,cAAc,GAAG,UAAU,CAAC;YAChC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,cAAc;YACzB,MAAM,EAAE,cAAc;YACtB,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,SAAS;YAClC,QAAQ,EAAE,EAAE;YACZ,uBAAuB,EAAE,GAAG,CAAC,iBAAiB;SAC/C,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,GAAmB;IAC9D,OAAO,CAAC,KAAU,EAAE,EAAE;QACpB,MAAM,cAAc,GAAG,UAAU,CAAC;YAChC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,kBAAkB;YAC7B,MAAM,EAAE,kBAAkB;YAC1B,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,SAAS;YAClC,QAAQ,EAAE,EAAE;YACZ,uBAAuB,EAAE,GAAG,CAAC,iBAAiB;SAC/C,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HttpsSender } from "../transport/https-sender.js";
|
|
2
|
+
import type { RateTracker } from "../severity.js";
|
|
3
|
+
import type { LocalFailsafe } from "../kill-switch/local-failsafe.js";
|
|
4
|
+
import type { RuleCache } from "../rule-cache.js";
|
|
5
|
+
interface ToolCallContext {
|
|
6
|
+
agentId: string;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
sender: HttpsSender;
|
|
9
|
+
rateTracker: RateTracker;
|
|
10
|
+
redactionPatterns: string[];
|
|
11
|
+
failsafe: LocalFailsafe;
|
|
12
|
+
ruleCache: RuleCache;
|
|
13
|
+
}
|
|
14
|
+
export declare function createBeforeToolCallHandler(ctx: ToolCallContext): (event: any) => {
|
|
15
|
+
block: boolean;
|
|
16
|
+
blockReason: string | undefined;
|
|
17
|
+
} | undefined;
|
|
18
|
+
export declare function createAfterToolCallHandler(ctx: ToolCallContext): (event: any) => void;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=tool-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call.d.ts","sourceRoot":"","sources":["../../src/hooks/tool-call.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,eAAe,IACtD,OAAO,GAAG;;;cA+DnB;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,eAAe,IACrD,OAAO,GAAG,UA+BnB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { buildEvent } from "../event-builder.js";
|
|
2
|
+
import { killState } from "../kill-switch/kill-state.js";
|
|
3
|
+
export function createBeforeToolCallHandler(ctx) {
|
|
4
|
+
return (event) => {
|
|
5
|
+
ctx.rateTracker.record();
|
|
6
|
+
ctx.failsafe.recordToolCall();
|
|
7
|
+
// Record event in rule cache for time-window based rules
|
|
8
|
+
ctx.ruleCache.recordEvent({
|
|
9
|
+
timestamp: Date.now(),
|
|
10
|
+
toolName: event.toolName,
|
|
11
|
+
eventType: "tool_use",
|
|
12
|
+
costUsd: event.cost,
|
|
13
|
+
action: event.toolName,
|
|
14
|
+
target: event.toolName,
|
|
15
|
+
});
|
|
16
|
+
const clawnitorEvent = buildEvent({
|
|
17
|
+
agentId: ctx.agentId,
|
|
18
|
+
sessionId: ctx.sessionId,
|
|
19
|
+
eventType: "tool_use",
|
|
20
|
+
action: `before: ${event.toolName || "unknown"}`,
|
|
21
|
+
target: event.toolName || "unknown",
|
|
22
|
+
metadata: {
|
|
23
|
+
tool_name: event.toolName,
|
|
24
|
+
...(event.params ? { raw_snippet: JSON.stringify(event.params).slice(0, 500) } : {}),
|
|
25
|
+
},
|
|
26
|
+
rateTracker: ctx.rateTracker,
|
|
27
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
28
|
+
});
|
|
29
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
30
|
+
// 1. Check kill state (server-triggered)
|
|
31
|
+
if (killState.isKilled()) {
|
|
32
|
+
return {
|
|
33
|
+
block: true,
|
|
34
|
+
blockReason: `Clawnitor: agent paused — ${killState.getReason() || "unknown reason"}`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// 2. Check local failsafe (spend/rate/blocklist)
|
|
38
|
+
const failsafeResult = ctx.failsafe.check(event.toolName || "");
|
|
39
|
+
if (failsafeResult.block) {
|
|
40
|
+
killState.setKilled(failsafeResult.reason);
|
|
41
|
+
return {
|
|
42
|
+
block: true,
|
|
43
|
+
blockReason: failsafeResult.reason,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// 3. Check cached server rules locally (PRE-ACTION for pattern rules)
|
|
47
|
+
const ruleResult = ctx.ruleCache.checkBeforeToolCall(event.toolName || "", event.params);
|
|
48
|
+
if (ruleResult.blocked) {
|
|
49
|
+
killState.setKilled(ruleResult.reason || "Rule triggered");
|
|
50
|
+
return {
|
|
51
|
+
block: true,
|
|
52
|
+
blockReason: ruleResult.reason,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function createAfterToolCallHandler(ctx) {
|
|
59
|
+
return (event) => {
|
|
60
|
+
// Track spend for failsafe and rule cache
|
|
61
|
+
if (typeof event.cost === "number") {
|
|
62
|
+
ctx.failsafe.addSpend(event.cost);
|
|
63
|
+
ctx.ruleCache.recordEvent({
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
toolName: event.toolName,
|
|
66
|
+
eventType: "tool_use",
|
|
67
|
+
costUsd: event.cost,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const clawnitorEvent = buildEvent({
|
|
71
|
+
agentId: ctx.agentId,
|
|
72
|
+
sessionId: ctx.sessionId,
|
|
73
|
+
eventType: "tool_use",
|
|
74
|
+
action: `after: ${event.toolName || "unknown"}`,
|
|
75
|
+
target: event.toolName || "unknown",
|
|
76
|
+
metadata: {
|
|
77
|
+
tool_name: event.toolName,
|
|
78
|
+
duration_ms: event.duration,
|
|
79
|
+
error: event.error?.message,
|
|
80
|
+
cost_usd: event.cost,
|
|
81
|
+
raw_snippet: event.result ? String(event.result).slice(0, 500) : undefined,
|
|
82
|
+
},
|
|
83
|
+
rateTracker: ctx.rateTracker,
|
|
84
|
+
customRedactionPatterns: ctx.redactionPatterns,
|
|
85
|
+
});
|
|
86
|
+
ctx.sender.enqueue(clawnitorEvent);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=tool-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call.js","sourceRoot":"","sources":["../../src/hooks/tool-call.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyBA,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QA0GxC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { parseConfig } from "./config.js";
|
|
2
|
+
import { HttpsSender } from "./transport/https-sender.js";
|
|
3
|
+
import { SqliteCache } from "./transport/sqlite-cache.js";
|
|
4
|
+
import { WebSocketClient } from "./transport/websocket-client.js";
|
|
5
|
+
import { createRateTracker } from "./severity.js";
|
|
6
|
+
import { killState } from "./kill-switch/kill-state.js";
|
|
7
|
+
import { LocalFailsafe } from "./kill-switch/local-failsafe.js";
|
|
8
|
+
import { RuleCache } from "./rule-cache.js";
|
|
9
|
+
import { createBeforeToolCallHandler, createAfterToolCallHandler, } from "./hooks/tool-call.js";
|
|
10
|
+
import { createLlmInputHandler, createLlmOutputHandler } from "./hooks/llm.js";
|
|
11
|
+
import { createMessageSendingHandler, createMessageSentHandler, createMessageReceivedHandler, } from "./hooks/message.js";
|
|
12
|
+
import { createSessionStartHandler, createSessionEndHandler, createAgentEndHandler, createSubagentHandlers, } from "./hooks/lifecycle.js";
|
|
13
|
+
export default function register(api) {
|
|
14
|
+
const rawConfig = api.config || {};
|
|
15
|
+
const config = parseConfig(rawConfig);
|
|
16
|
+
const rateTracker = createRateTracker();
|
|
17
|
+
const failsafe = new LocalFailsafe(config);
|
|
18
|
+
const ruleCache = new RuleCache(config);
|
|
19
|
+
// Initialize SQLite cache for offline resilience
|
|
20
|
+
const cache = new SqliteCache();
|
|
21
|
+
// Initialize HTTPS sender
|
|
22
|
+
const sender = new HttpsSender(config, {
|
|
23
|
+
onKillState: (killed, reason) => {
|
|
24
|
+
// HTTPS fallback for kill state
|
|
25
|
+
if (killed && !killState.isKilled()) {
|
|
26
|
+
killState.setKilled(reason || "Killed by server (HTTPS fallback)");
|
|
27
|
+
}
|
|
28
|
+
else if (!killed && killState.isKilled()) {
|
|
29
|
+
killState.clearKilled();
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
onFlushFail: (events) => {
|
|
33
|
+
cache.cache(events);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
sender.start();
|
|
37
|
+
// Initialize WebSocket client for real-time kill signals
|
|
38
|
+
const wsClient = new WebSocketClient(config, {
|
|
39
|
+
onKill: (reason, ruleId) => {
|
|
40
|
+
killState.setKilled(reason);
|
|
41
|
+
},
|
|
42
|
+
onUnkill: () => {
|
|
43
|
+
killState.clearKilled();
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
wsClient.start();
|
|
47
|
+
ruleCache.start();
|
|
48
|
+
// Periodically flush cached events
|
|
49
|
+
const cacheFlushInterval = setInterval(() => {
|
|
50
|
+
const cached = cache.flush(50);
|
|
51
|
+
if (cached.length > 0) {
|
|
52
|
+
for (const event of cached) {
|
|
53
|
+
sender.enqueue(event);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, 30_000);
|
|
57
|
+
// Shared context for all hooks
|
|
58
|
+
let currentSessionId = "default";
|
|
59
|
+
const agentId = rawConfig.agentId || "unknown";
|
|
60
|
+
const ctx = {
|
|
61
|
+
get agentId() {
|
|
62
|
+
return agentId;
|
|
63
|
+
},
|
|
64
|
+
get sessionId() {
|
|
65
|
+
return currentSessionId;
|
|
66
|
+
},
|
|
67
|
+
sender,
|
|
68
|
+
rateTracker,
|
|
69
|
+
redactionPatterns: config.redactionPatterns,
|
|
70
|
+
failsafe,
|
|
71
|
+
ruleCache,
|
|
72
|
+
};
|
|
73
|
+
// Register hooks
|
|
74
|
+
api.on("before_tool_call", createBeforeToolCallHandler(ctx), {
|
|
75
|
+
priority: 10,
|
|
76
|
+
});
|
|
77
|
+
api.on("after_tool_call", createAfterToolCallHandler(ctx), { priority: 10 });
|
|
78
|
+
api.on("llm_input", createLlmInputHandler(ctx), { priority: 10 });
|
|
79
|
+
api.on("llm_output", createLlmOutputHandler(ctx), { priority: 10 });
|
|
80
|
+
api.on("message_sending", createMessageSendingHandler(ctx), {
|
|
81
|
+
priority: 10,
|
|
82
|
+
});
|
|
83
|
+
api.on("message_sent", createMessageSentHandler(ctx), { priority: 10 });
|
|
84
|
+
api.on("message_received", createMessageReceivedHandler(ctx), {
|
|
85
|
+
priority: 10,
|
|
86
|
+
});
|
|
87
|
+
api.on("session_start", createSessionStartHandler({
|
|
88
|
+
...ctx,
|
|
89
|
+
onSessionStart: (sid) => {
|
|
90
|
+
currentSessionId = sid;
|
|
91
|
+
failsafe.resetSession();
|
|
92
|
+
},
|
|
93
|
+
}), { priority: 10 });
|
|
94
|
+
api.on("session_end", createSessionEndHandler({
|
|
95
|
+
...ctx,
|
|
96
|
+
onSessionEnd: () => {
|
|
97
|
+
currentSessionId = "default";
|
|
98
|
+
},
|
|
99
|
+
}), { priority: 10 });
|
|
100
|
+
api.on("agent_end", createAgentEndHandler(ctx), { priority: 10 });
|
|
101
|
+
const subagent = createSubagentHandlers(ctx);
|
|
102
|
+
api.on("subagent_spawning", subagent.spawning, { priority: 10 });
|
|
103
|
+
api.on("subagent_ended", subagent.ended, { priority: 10 });
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|