podwatch 1.0.2

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.
Files changed (51) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +92 -0
  3. package/bin/podwatch.js +10 -0
  4. package/dist/classifier.d.ts +22 -0
  5. package/dist/classifier.d.ts.map +1 -0
  6. package/dist/classifier.js +157 -0
  7. package/dist/classifier.js.map +1 -0
  8. package/dist/hooks/cost.d.ts +26 -0
  9. package/dist/hooks/cost.d.ts.map +1 -0
  10. package/dist/hooks/cost.js +107 -0
  11. package/dist/hooks/cost.js.map +1 -0
  12. package/dist/hooks/lifecycle.d.ts +16 -0
  13. package/dist/hooks/lifecycle.d.ts.map +1 -0
  14. package/dist/hooks/lifecycle.js +273 -0
  15. package/dist/hooks/lifecycle.js.map +1 -0
  16. package/dist/hooks/security.d.ts +19 -0
  17. package/dist/hooks/security.d.ts.map +1 -0
  18. package/dist/hooks/security.js +128 -0
  19. package/dist/hooks/security.js.map +1 -0
  20. package/dist/hooks/sessions.d.ts +10 -0
  21. package/dist/hooks/sessions.d.ts.map +1 -0
  22. package/dist/hooks/sessions.js +53 -0
  23. package/dist/hooks/sessions.js.map +1 -0
  24. package/dist/index.d.ts +32 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +120 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/redact.d.ts +35 -0
  29. package/dist/redact.d.ts.map +1 -0
  30. package/dist/redact.js +372 -0
  31. package/dist/redact.js.map +1 -0
  32. package/dist/scanner.d.ts +27 -0
  33. package/dist/scanner.d.ts.map +1 -0
  34. package/dist/scanner.js +117 -0
  35. package/dist/scanner.js.map +1 -0
  36. package/dist/transmitter.d.ts +58 -0
  37. package/dist/transmitter.d.ts.map +1 -0
  38. package/dist/transmitter.js +654 -0
  39. package/dist/transmitter.js.map +1 -0
  40. package/dist/types.d.ts +116 -0
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/types.js +9 -0
  43. package/dist/types.js.map +1 -0
  44. package/dist/updater.d.ts +168 -0
  45. package/dist/updater.d.ts.map +1 -0
  46. package/dist/updater.js +579 -0
  47. package/dist/updater.js.map +1 -0
  48. package/lib/installer.js +599 -0
  49. package/openclaw.plugin.json +59 -0
  50. package/package.json +56 -0
  51. package/skills/podwatch/SKILL.md +112 -0
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ /**
3
+ * Lifecycle handlers — gateway_start, gateway_stop, before_compaction.
4
+ *
5
+ * register(): starts pulse interval + initial skill/plugin scan
6
+ * gateway_stop: flushes pending events, stops intervals
7
+ * before_compaction: tracks context window pressure
8
+ *
9
+ * Pulse = Podwatch plugin's lightweight alive-ping (direct HTTP, no LLM cost).
10
+ * This is NOT OpenClaw's agent heartbeat (which triggers LLM turns).
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.registerLifecycleHandlers = registerLifecycleHandlers;
47
+ const transmitter_js_1 = require("../transmitter.js");
48
+ const scanner_js_1 = require("../scanner.js");
49
+ const fs = __importStar(require("node:fs"));
50
+ const path = __importStar(require("node:path"));
51
+ const PLUGIN_VERSION = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", "package.json"), "utf-8")).version;
52
+ let pulseTimer = null;
53
+ let scanTimer = null;
54
+ // Pulse backoff state
55
+ let pulseFailureCount = 0;
56
+ const PULSE_FAILURE_THRESHOLD = 3; // Start backoff after N consecutive failures
57
+ const PULSE_MAX_INTERVAL_MS = 3_600_000; // 60 min cap
58
+ // Config change detection state
59
+ let knownPrimaryModel = null;
60
+ /**
61
+ * Read the primary model from the OpenClaw gateway config.
62
+ * Handles both string and object shapes for `agents.defaults.model`.
63
+ */
64
+ function readPrimaryModel(api) {
65
+ try {
66
+ const modelCfg = api.config?.agents?.defaults?.model;
67
+ if (!modelCfg)
68
+ return null;
69
+ if (typeof modelCfg === "string")
70
+ return modelCfg;
71
+ if (typeof modelCfg === "object" && modelCfg.primary)
72
+ return String(modelCfg.primary);
73
+ return null;
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ /**
80
+ * Check if the primary model changed and emit a config_change event if so.
81
+ */
82
+ function checkModelConfigChange(api) {
83
+ const currentModel = readPrimaryModel(api);
84
+ if (currentModel === knownPrimaryModel)
85
+ return;
86
+ const previousValue = knownPrimaryModel;
87
+ knownPrimaryModel = currentModel;
88
+ // Don't emit on first read if null
89
+ if (currentModel === null && previousValue === null)
90
+ return;
91
+ transmitter_js_1.transmitter.enqueue({
92
+ type: "config_change",
93
+ ts: Date.now(),
94
+ field: "model.primary",
95
+ value: currentModel,
96
+ previousValue,
97
+ // Pass as params so they appear in toolArgs on the server
98
+ params: {
99
+ field: "model.primary",
100
+ value: currentModel,
101
+ previousValue,
102
+ },
103
+ });
104
+ }
105
+ /**
106
+ * Register lifecycle hook handlers.
107
+ */
108
+ function registerLifecycleHandlers(api, config) {
109
+ const endpoint = config.endpoint ?? "https://podwatch.app/api";
110
+ const apiKey = config.apiKey;
111
+ // -----------------------------------------------------------------------
112
+ // Pulse + scan — run immediately during register() since
113
+ // gateway_start is never emitted to plugins.
114
+ // -----------------------------------------------------------------------
115
+ const basePulseIntervalMs = config.pulseIntervalMs ?? 300_000;
116
+ // Reset pulse backoff state
117
+ pulseFailureCount = 0;
118
+ // Read initial primary model config and send config_change event
119
+ knownPrimaryModel = null; // Reset on re-register
120
+ checkModelConfigChange(api);
121
+ // Send initial pulse right now
122
+ void sendPulseWithBackoff(endpoint, apiKey, basePulseIntervalMs, api);
123
+ // Initial skill/plugin scan — delayed 30s to let gateway fully settle
124
+ const workspaceDir = api.config?.agents?.defaults?.workspace;
125
+ setTimeout(() => void runScan(workspaceDir), 30_000);
126
+ // Start periodic scan interval (default 6h)
127
+ if (scanTimer)
128
+ clearInterval(scanTimer);
129
+ scanTimer = setInterval(() => void runScan(workspaceDir), config.scanIntervalMs ?? 21_600_000);
130
+ if (scanTimer && typeof scanTimer === "object" && "unref" in scanTimer) {
131
+ scanTimer.unref();
132
+ }
133
+ api.logger.info(`[podwatch/lifecycle] Pulse & scan started from register(). Pulse: ${config.pulseIntervalMs ?? 300_000}ms, Scan: ${config.scanIntervalMs ?? 21_600_000}ms`);
134
+ // -----------------------------------------------------------------------
135
+ // gateway_start — best-effort re-scan (in case it ever fires)
136
+ // -----------------------------------------------------------------------
137
+ api.on("gateway_start", async (event) => {
138
+ // Re-run scan as best-effort; pulse is already running
139
+ void runScan(api.config?.agents?.defaults?.workspace);
140
+ }, { name: "podwatch-gateway-start" });
141
+ // -----------------------------------------------------------------------
142
+ // gateway_stop — graceful shutdown
143
+ // -----------------------------------------------------------------------
144
+ api.on("gateway_stop", async () => {
145
+ // Stop intervals
146
+ if (pulseTimer) {
147
+ clearTimeout(pulseTimer);
148
+ pulseTimer = null;
149
+ }
150
+ if (scanTimer) {
151
+ clearInterval(scanTimer);
152
+ scanTimer = null;
153
+ }
154
+ // Unsubscribe from diagnostic events
155
+ const unsubscribe = api.__podwatch_unsubscribeDiagnostics;
156
+ if (typeof unsubscribe === "function") {
157
+ unsubscribe();
158
+ }
159
+ // Flush remaining events
160
+ await transmitter_js_1.transmitter.shutdown();
161
+ api.logger.info("[podwatch/lifecycle] Graceful shutdown complete");
162
+ }, { name: "podwatch-gateway-stop" });
163
+ // -----------------------------------------------------------------------
164
+ // before_compaction — context window pressure
165
+ // -----------------------------------------------------------------------
166
+ api.on("before_compaction", async (event, ctx) => {
167
+ transmitter_js_1.transmitter.enqueue({
168
+ type: "compaction",
169
+ ts: Date.now(),
170
+ messageCount: event.messageCount,
171
+ tokenCount: event.tokenCount,
172
+ sessionKey: ctx.sessionKey,
173
+ agentId: ctx.agentId,
174
+ });
175
+ // Context pressure alert — only if both fields are available
176
+ if (typeof event.tokenCount === "number" &&
177
+ typeof event.contextLimit === "number") {
178
+ const contextLimit = event.contextLimit;
179
+ const ratio = event.tokenCount / contextLimit;
180
+ if (ratio > 0.8) {
181
+ transmitter_js_1.transmitter.enqueue({
182
+ type: "alert",
183
+ ts: Date.now(),
184
+ severity: "warning",
185
+ pattern: "context_pressure",
186
+ tokenCount: event.tokenCount,
187
+ contextLimit,
188
+ ratio,
189
+ sessionKey: ctx.sessionKey,
190
+ agentId: ctx.agentId,
191
+ });
192
+ }
193
+ }
194
+ }, { name: "podwatch-compaction" });
195
+ }
196
+ // ---------------------------------------------------------------------------
197
+ // Helpers
198
+ // ---------------------------------------------------------------------------
199
+ /**
200
+ * Send a lightweight pulse directly to the Podwatch API, then schedule
201
+ * the next pulse. Uses exponential backoff after consecutive failures.
202
+ *
203
+ * Backoff kicks in after PULSE_FAILURE_THRESHOLD (3) consecutive failures:
204
+ * base → 2x base → 4x base → ... capped at PULSE_MAX_INTERVAL_MS (60min)
205
+ * Resets to base interval on success.
206
+ */
207
+ async function sendPulseWithBackoff(endpoint, apiKey, baseIntervalMs, api) {
208
+ // Check for config changes on each pulse
209
+ if (api) {
210
+ checkModelConfigChange(api);
211
+ }
212
+ let success = false;
213
+ try {
214
+ const response = await fetch(`${endpoint}/pulse`, {
215
+ method: "POST",
216
+ headers: {
217
+ "Content-Type": "application/json",
218
+ "Authorization": `Bearer ${apiKey}`,
219
+ },
220
+ body: JSON.stringify({
221
+ ts: Date.now(),
222
+ bufferedEvents: transmitter_js_1.transmitter.bufferedCount,
223
+ uptimeHours: transmitter_js_1.transmitter.getAgentUptimeHours(),
224
+ pluginVersion: PLUGIN_VERSION,
225
+ }),
226
+ signal: AbortSignal.timeout(10_000),
227
+ });
228
+ if (response.ok) {
229
+ success = true;
230
+ }
231
+ else {
232
+ console.error(`[podwatch/pulse] API ${response.status}`);
233
+ }
234
+ }
235
+ catch (err) {
236
+ console.error("[podwatch/pulse] Failed:", err);
237
+ }
238
+ // Update failure counter
239
+ if (success) {
240
+ pulseFailureCount = 0;
241
+ }
242
+ else {
243
+ pulseFailureCount++;
244
+ }
245
+ // Calculate next interval
246
+ let nextIntervalMs = baseIntervalMs;
247
+ if (pulseFailureCount >= PULSE_FAILURE_THRESHOLD) {
248
+ // Exponential backoff: 2x base per failure beyond threshold
249
+ const backoffMultiplier = Math.pow(2, pulseFailureCount - PULSE_FAILURE_THRESHOLD);
250
+ nextIntervalMs = Math.min(baseIntervalMs * 2 * backoffMultiplier, PULSE_MAX_INTERVAL_MS);
251
+ }
252
+ // Schedule next pulse
253
+ if (pulseTimer)
254
+ clearTimeout(pulseTimer);
255
+ pulseTimer = setTimeout(() => void sendPulseWithBackoff(endpoint, apiKey, baseIntervalMs, api), nextIntervalMs);
256
+ if (pulseTimer && typeof pulseTimer === "object" && "unref" in pulseTimer) {
257
+ pulseTimer.unref();
258
+ }
259
+ }
260
+ async function runScan(workspaceDir) {
261
+ try {
262
+ const results = await (0, scanner_js_1.scanSkillsAndPlugins)(workspaceDir);
263
+ transmitter_js_1.transmitter.enqueue({
264
+ type: "scan",
265
+ ts: Date.now(),
266
+ ...results,
267
+ });
268
+ }
269
+ catch (err) {
270
+ console.error("[podwatch/lifecycle] Scan failed:", err);
271
+ }
272
+ }
273
+ //# 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,19 @@
1
+ /**
2
+ * Security handlers — before_tool_call and after_tool_call.
3
+ *
4
+ * before_tool_call: THE critical hook. Can BLOCK tool execution.
5
+ * - A) Budget enforcement (blocks when daily spend >= 95% of limit)
6
+ * - B1) Exfiltration sequence detection (credential read → network call)
7
+ * - B2) First-time tool detection (unknown tool after 24h uptime)
8
+ * - B3) Log ALL tool calls with redacted params (server classifies risk)
9
+ *
10
+ * after_tool_call: Fire-and-forget.
11
+ * - Latency tracking (durationMs)
12
+ * - Success/failure recording
13
+ */
14
+ import type { PodwatchConfig } from "../index.js";
15
+ /**
16
+ * Register security hook handlers.
17
+ */
18
+ export declare function registerSecurityHandlers(api: any, config: PodwatchConfig): void;
19
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/hooks/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAalD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CA8H/E"}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ /**
3
+ * Security handlers — before_tool_call and after_tool_call.
4
+ *
5
+ * before_tool_call: THE critical hook. Can BLOCK tool execution.
6
+ * - A) Budget enforcement (blocks when daily spend >= 95% of limit)
7
+ * - B1) Exfiltration sequence detection (credential read → network call)
8
+ * - B2) First-time tool detection (unknown tool after 24h uptime)
9
+ * - B3) Log ALL tool calls with redacted params (server classifies risk)
10
+ *
11
+ * after_tool_call: Fire-and-forget.
12
+ * - Latency tracking (durationMs)
13
+ * - Success/failure recording
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.registerSecurityHandlers = registerSecurityHandlers;
17
+ const transmitter_js_1 = require("../transmitter.js");
18
+ const redact_js_1 = require("../redact.js");
19
+ const classifier_js_1 = require("../classifier.js");
20
+ const BUDGET_TOLERANCE = 0.95; // Block at 95% of limit
21
+ /**
22
+ * Register security hook handlers.
23
+ */
24
+ function registerSecurityHandlers(api, config) {
25
+ // -----------------------------------------------------------------------
26
+ // before_tool_call — security scan + budget enforcement + exfiltration
27
+ // -----------------------------------------------------------------------
28
+ api.on("before_tool_call", async (event, ctx) => {
29
+ const { toolName, params } = event;
30
+ // --- A) Budget check (if enabled) — can BLOCK ---
31
+ if (config.enableBudgetEnforcement) {
32
+ const budget = transmitter_js_1.transmitter.getCachedBudget();
33
+ if (budget && budget.limit > 0 && budget.currentSpend >= budget.limit * BUDGET_TOLERANCE) {
34
+ transmitter_js_1.transmitter.enqueue({
35
+ type: "budget_blocked",
36
+ ts: Date.now(),
37
+ toolName,
38
+ sessionKey: ctx.sessionKey,
39
+ agentId: ctx.agentId,
40
+ budgetLimit: budget.limit,
41
+ currentSpend: budget.currentSpend,
42
+ });
43
+ return {
44
+ block: true,
45
+ blockReason: `Podwatch: Daily budget of $${budget.limit.toFixed(2)} reached ($${budget.currentSpend.toFixed(2)} spent). Manage at podwatch.app/settings`,
46
+ };
47
+ }
48
+ }
49
+ // --- B) Security alerts (if enabled) ---
50
+ if (config.enableSecurityAlerts) {
51
+ const classification = (0, classifier_js_1.classifyTool)(toolName, params);
52
+ // B1) Exfiltration sequence detection
53
+ if (classification.accessesCredentials) {
54
+ transmitter_js_1.transmitter.markCredentialAccess(toolName, params);
55
+ }
56
+ if (classification.makesNetworkCall && transmitter_js_1.transmitter.hasRecentCredentialAccess(60)) {
57
+ const recentAccess = transmitter_js_1.transmitter.getRecentCredentialAccess(60);
58
+ transmitter_js_1.transmitter.enqueue({
59
+ type: "security",
60
+ ts: Date.now(),
61
+ pattern: "exfiltration_sequence",
62
+ severity: "critical",
63
+ toolName,
64
+ reason: `Network call (${toolName}) detected within 60s of credential access (${recentAccess?.toolName ?? "unknown"} → ${recentAccess?.path ?? "unknown"})`,
65
+ sessionKey: ctx.sessionKey,
66
+ agentId: ctx.agentId,
67
+ });
68
+ }
69
+ // B1b) Persistence attempt detection
70
+ if (classification.persistenceAttempt) {
71
+ transmitter_js_1.transmitter.enqueue({
72
+ type: "security",
73
+ ts: Date.now(),
74
+ pattern: "persistence_attempt",
75
+ severity: "high",
76
+ toolName,
77
+ reason: `Persistence attempt detected via ${toolName}`,
78
+ sessionKey: ctx.sessionKey,
79
+ agentId: ctx.agentId,
80
+ });
81
+ }
82
+ // B2) First-time tool detection
83
+ if (!transmitter_js_1.transmitter.isKnownTool(toolName) && transmitter_js_1.transmitter.getAgentUptimeHours() > 24) {
84
+ transmitter_js_1.transmitter.enqueue({
85
+ type: "security",
86
+ ts: Date.now(),
87
+ pattern: "first_time_tool",
88
+ severity: "medium",
89
+ toolName,
90
+ reason: `First use of tool "${toolName}" after ${Math.round(transmitter_js_1.transmitter.getAgentUptimeHours())}h uptime`,
91
+ sessionKey: ctx.sessionKey,
92
+ agentId: ctx.agentId,
93
+ });
94
+ }
95
+ transmitter_js_1.transmitter.recordToolSeen(toolName);
96
+ }
97
+ // --- B3) Log ALL tool calls for timeline (server classifies risk) ---
98
+ const { result: redactedParams, redactedCount } = (0, redact_js_1.redactParams)(params);
99
+ transmitter_js_1.transmitter.enqueue({
100
+ type: "tool_call",
101
+ ts: Date.now(),
102
+ toolName,
103
+ params: redactedParams,
104
+ redactedCount,
105
+ sessionKey: ctx.sessionKey,
106
+ agentId: ctx.agentId,
107
+ });
108
+ }, { name: "podwatch-security-scan", priority: 10 } // Run early to block before other plugins
109
+ );
110
+ // -----------------------------------------------------------------------
111
+ // after_tool_call — latency + success/failure (fire-and-forget)
112
+ // -----------------------------------------------------------------------
113
+ api.on("after_tool_call", async (event, ctx) => {
114
+ transmitter_js_1.transmitter.enqueue({
115
+ type: "tool_result",
116
+ ts: Date.now(),
117
+ toolName: event.toolName,
118
+ durationMs: event.durationMs,
119
+ success: !event.error,
120
+ error: event.error ? String(event.error).slice(0, 500) : undefined,
121
+ sessionKey: ctx.sessionKey,
122
+ agentId: ctx.agentId,
123
+ });
124
+ }, { name: "podwatch-tool-result" });
125
+ api.logger.info(`[podwatch/security] Handlers registered. Budget: ${config.enableBudgetEnforcement ? "ENFORCE" : "off"}, ` +
126
+ `Security: ${config.enableSecurityAlerts ? "ON" : "off"}`);
127
+ }
128
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/hooks/security.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Session handlers — session_start and session_end.
3
+ *
4
+ * Tracks session lifecycle for timeline, loop detection, and duration metrics.
5
+ */
6
+ /**
7
+ * Register session lifecycle handlers.
8
+ */
9
+ export declare function registerSessionHandlers(api: any): void;
10
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/hooks/sessions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAkDtD"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * Session handlers — session_start and session_end.
4
+ *
5
+ * Tracks session lifecycle for timeline, loop detection, and duration metrics.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.registerSessionHandlers = registerSessionHandlers;
9
+ const transmitter_js_1 = require("../transmitter.js");
10
+ /**
11
+ * Register session lifecycle handlers.
12
+ */
13
+ function registerSessionHandlers(api) {
14
+ // -----------------------------------------------------------------------
15
+ // session_start
16
+ // -----------------------------------------------------------------------
17
+ api.on("session_start", async (event, ctx) => {
18
+ transmitter_js_1.transmitter.enqueue({
19
+ type: "session_start",
20
+ ts: Date.now(),
21
+ sessionId: event.sessionId,
22
+ resumedFrom: event.resumedFrom,
23
+ agentId: ctx.agentId,
24
+ });
25
+ }, { name: "podwatch-session-start" });
26
+ // -----------------------------------------------------------------------
27
+ // session_end — includes loop detection
28
+ // -----------------------------------------------------------------------
29
+ api.on("session_end", async (event, ctx) => {
30
+ transmitter_js_1.transmitter.enqueue({
31
+ type: "session_end",
32
+ ts: Date.now(),
33
+ sessionId: event.sessionId,
34
+ messageCount: event.messageCount,
35
+ durationMs: event.durationMs,
36
+ agentId: ctx.agentId,
37
+ });
38
+ // Simple loop detection: sessions with > 100 messages are suspicious
39
+ if (event.messageCount > 100) {
40
+ transmitter_js_1.transmitter.enqueue({
41
+ type: "alert",
42
+ ts: Date.now(),
43
+ severity: "warning",
44
+ pattern: "session_loop_warning",
45
+ sessionKey: ctx.sessionId,
46
+ messageCount: event.messageCount,
47
+ agentId: ctx.agentId,
48
+ });
49
+ }
50
+ }, { name: "podwatch-session-end" });
51
+ api.logger.info("[podwatch/sessions] Session lifecycle handlers registered");
52
+ }
53
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/hooks/sessions.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAWH,0DAkDC;AAvDD,sDAAgD;AAEhD;;GAEG;AACH,SAAgB,uBAAuB,CAAC,GAAQ;IAC9C,0EAA0E;IAC1E,gBAAgB;IAChB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,CACJ,eAAe,EACf,KAAK,EAAE,KAAwB,EAAE,GAA4C,EAAiB,EAAE;QAC9F,4BAAW,CAAC,OAAO,CAAC;YAClB,IAAI,EAAE,eAAe;YACrB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,OAAO,EAAE,GAAG,CAAC,OAAO;SACrB,CAAC,CAAC;IACL,CAAC,EACD,EAAE,IAAI,EAAE,wBAAwB,EAAE,CACnC,CAAC;IAEF,0EAA0E;IAC1E,wCAAwC;IACxC,0EAA0E;IAC1E,GAAG,CAAC,EAAE,CACJ,aAAa,EACb,KAAK,EAAE,KAAsB,EAAE,GAA4C,EAAiB,EAAE;QAC5F,4BAAW,CAAC,OAAO,CAAC;YAClB,IAAI,EAAE,aAAa;YACnB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,OAAO,EAAE,GAAG,CAAC,OAAO;SACrB,CAAC,CAAC;QAEH,qEAAqE;QACrE,IAAI,KAAK,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC;YAC7B,4BAAW,CAAC,OAAO,CAAC;gBAClB,IAAI,EAAE,OAAO;gBACb,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,sBAAsB;gBAC/B,UAAU,EAAE,GAAG,CAAC,SAAS;gBACzB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,OAAO,EAAE,GAAG,CAAC,OAAO;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC,EACD,EAAE,IAAI,EAAE,sBAAsB,EAAE,CACjC,CAAC;IAEF,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Podwatch Plugin — OpenClaw cost monitoring, budget enforcement, and security alerts.
3
+ *
4
+ * Registers hook handlers and subscribes to diagnostic events to capture:
5
+ * - Cost/token data per LLM call (onDiagnosticEvent → model.usage)
6
+ * - Tool security scanning + budget blocking (before_tool_call)
7
+ * - Tool latency + success/failure (after_tool_call)
8
+ * - Session lifecycle (session_start, session_end)
9
+ * - Context pressure (before_compaction)
10
+ * - Pulse alive-ping + skill/plugin scanning (register())
11
+ * - Graceful shutdown (gateway_stop)
12
+ */
13
+ import type { PluginApi } from "./types.js";
14
+ export interface PodwatchConfig {
15
+ apiKey: string;
16
+ endpoint?: string;
17
+ enableBudgetEnforcement?: boolean;
18
+ enableSecurityAlerts?: boolean;
19
+ /** Enable auto-update of the plugin. Default: false (opt-in for security). */
20
+ autoUpdate?: boolean;
21
+ /** Pulse alive-ping interval in ms (default 300000 = 5 min). */
22
+ pulseIntervalMs?: number;
23
+ /** @deprecated Use pulseIntervalMs instead. Kept for backward compatibility. */
24
+ heartbeatIntervalMs?: number;
25
+ scanIntervalMs?: number;
26
+ }
27
+ /**
28
+ * OpenClaw plugin entry point.
29
+ * Called by the Gateway when the plugin is loaded.
30
+ */
31
+ export default function register(api: PluginApi): void;
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,YAAY,CAAC;AAY5D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAwBD;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAiErD"}