@phuetz/code-buddy 0.1.12 → 0.1.14
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 +228 -13
- package/dist/agent/architect-mode.d.ts +11 -0
- package/dist/agent/architect-mode.js +133 -25
- package/dist/agent/architect-mode.js.map +1 -1
- package/dist/agent/codebuddy-agent.d.ts +24 -0
- package/dist/agent/codebuddy-agent.js +118 -16
- package/dist/agent/codebuddy-agent.js.map +1 -1
- package/dist/agent/execution/agent-executor.d.ts +9 -0
- package/dist/agent/execution/agent-executor.js +62 -1
- package/dist/agent/execution/agent-executor.js.map +1 -1
- package/dist/agent/message-queue.d.ts +77 -0
- package/dist/agent/message-queue.js +116 -0
- package/dist/agent/message-queue.js.map +1 -0
- package/dist/agent/middleware/auto-observation.d.ts +37 -0
- package/dist/agent/middleware/auto-observation.js +231 -0
- package/dist/agent/middleware/auto-observation.js.map +1 -0
- package/dist/agent/middleware/index.d.ts +2 -0
- package/dist/agent/middleware/index.js +1 -0
- package/dist/agent/middleware/index.js.map +1 -1
- package/dist/agent/tool-handler.js +3 -2
- package/dist/agent/tool-handler.js.map +1 -1
- package/dist/agent/turn-diff-tracker.js +3 -0
- package/dist/agent/turn-diff-tracker.js.map +1 -1
- package/dist/agent/types.d.ts +7 -2
- package/dist/analytics/budget-alerts.d.ts +81 -0
- package/dist/analytics/budget-alerts.js +126 -0
- package/dist/analytics/budget-alerts.js.map +1 -0
- package/dist/analytics/cost-predictor.d.ts +79 -0
- package/dist/analytics/cost-predictor.js +150 -0
- package/dist/analytics/cost-predictor.js.map +1 -0
- package/dist/analytics/index.d.ts +2 -0
- package/dist/analytics/index.js +2 -0
- package/dist/analytics/index.js.map +1 -1
- package/dist/auth/profile-manager.d.ts +205 -0
- package/dist/auth/profile-manager.js +484 -0
- package/dist/auth/profile-manager.js.map +1 -0
- package/dist/browser-automation/browser-manager.d.ts +79 -1
- package/dist/browser-automation/browser-manager.js +265 -2
- package/dist/browser-automation/browser-manager.js.map +1 -1
- package/dist/browser-automation/profile-manager.d.ts +32 -0
- package/dist/browser-automation/profile-manager.js +83 -0
- package/dist/browser-automation/profile-manager.js.map +1 -0
- package/dist/browser-automation/route-interceptor.d.ts +29 -0
- package/dist/browser-automation/route-interceptor.js +103 -0
- package/dist/browser-automation/route-interceptor.js.map +1 -0
- package/dist/browser-automation/screenshot-annotator.d.ts +23 -0
- package/dist/browser-automation/screenshot-annotator.js +86 -0
- package/dist/browser-automation/screenshot-annotator.js.map +1 -0
- package/dist/browser-automation/types.d.ts +47 -0
- package/dist/cache/llm-response-cache.js +3 -0
- package/dist/cache/llm-response-cache.js.map +1 -1
- package/dist/canvas/canvas-server.js +4 -3
- package/dist/canvas/canvas-server.js.map +1 -1
- package/dist/channels/discord/client.d.ts +2 -1
- package/dist/channels/discord/client.js +28 -16
- package/dist/channels/discord/client.js.map +1 -1
- package/dist/channels/dm-pairing.js +6 -3
- package/dist/channels/dm-pairing.js.map +1 -1
- package/dist/channels/google-chat/index.d.ts +210 -0
- package/dist/channels/google-chat/index.js +505 -0
- package/dist/channels/google-chat/index.js.map +1 -0
- package/dist/channels/group-security.d.ts +182 -0
- package/dist/channels/group-security.js +407 -0
- package/dist/channels/group-security.js.map +1 -0
- package/dist/channels/index.d.ts +17 -1
- package/dist/channels/index.js +16 -0
- package/dist/channels/index.js.map +1 -1
- package/dist/channels/matrix/index.d.ts +181 -0
- package/dist/channels/matrix/index.js +643 -0
- package/dist/channels/matrix/index.js.map +1 -0
- package/dist/channels/offline-queue.d.ts +92 -0
- package/dist/channels/offline-queue.js +112 -0
- package/dist/channels/offline-queue.js.map +1 -0
- package/dist/channels/reconnection-manager.d.ts +117 -0
- package/dist/channels/reconnection-manager.js +171 -0
- package/dist/channels/reconnection-manager.js.map +1 -0
- package/dist/channels/signal/index.d.ts +184 -0
- package/dist/channels/signal/index.js +488 -0
- package/dist/channels/signal/index.js.map +1 -0
- package/dist/channels/slack/client.d.ts +2 -1
- package/dist/channels/slack/client.js +30 -15
- package/dist/channels/slack/client.js.map +1 -1
- package/dist/channels/teams/index.d.ts +196 -0
- package/dist/channels/teams/index.js +477 -0
- package/dist/channels/teams/index.js.map +1 -0
- package/dist/channels/telegram/client.d.ts +3 -1
- package/dist/channels/telegram/client.js +29 -2
- package/dist/channels/telegram/client.js.map +1 -1
- package/dist/channels/webchat/index.d.ts +103 -0
- package/dist/channels/webchat/index.js +697 -0
- package/dist/channels/webchat/index.js.map +1 -0
- package/dist/channels/whatsapp/index.d.ts +105 -0
- package/dist/channels/whatsapp/index.js +533 -0
- package/dist/channels/whatsapp/index.js.map +1 -0
- package/dist/codebuddy/client.js +11 -5
- package/dist/codebuddy/client.js.map +1 -1
- package/dist/codebuddy/tool-definitions/advanced-tools.d.ts +1 -0
- package/dist/codebuddy/tool-definitions/advanced-tools.js +103 -3
- package/dist/codebuddy/tool-definitions/advanced-tools.js.map +1 -1
- package/dist/codebuddy/tool-definitions/index.d.ts +1 -1
- package/dist/codebuddy/tool-definitions/index.js +1 -1
- package/dist/codebuddy/tool-definitions/index.js.map +1 -1
- package/dist/codebuddy/tools.js +3 -1
- package/dist/codebuddy/tools.js.map +1 -1
- package/dist/commands/cli/config-command.d.ts +8 -0
- package/dist/commands/cli/config-command.js +90 -0
- package/dist/commands/cli/config-command.js.map +1 -0
- package/dist/commands/cli/openclaw-commands.d.ts +12 -0
- package/dist/commands/cli/openclaw-commands.js +446 -0
- package/dist/commands/cli/openclaw-commands.js.map +1 -0
- package/dist/commands/cli/utility-commands.js +30 -0
- package/dist/commands/cli/utility-commands.js.map +1 -1
- package/dist/commands/client-dispatcher.js +22 -2
- package/dist/commands/client-dispatcher.js.map +1 -1
- package/dist/commands/enhanced-command-handler.js +21 -2
- package/dist/commands/enhanced-command-handler.js.map +1 -1
- package/dist/commands/handlers/extra-handlers.d.ts +30 -0
- package/dist/commands/handlers/extra-handlers.js +547 -0
- package/dist/commands/handlers/extra-handlers.js.map +1 -0
- package/dist/commands/handlers/index.d.ts +1 -0
- package/dist/commands/handlers/index.js +2 -0
- package/dist/commands/handlers/index.js.map +1 -1
- package/dist/commands/slash/builtin-commands.js +41 -34
- package/dist/commands/slash/builtin-commands.js.map +1 -1
- package/dist/config/env-schema.d.ts +58 -0
- package/dist/config/env-schema.js +789 -0
- package/dist/config/env-schema.js.map +1 -0
- package/dist/config/feature-flags.js +2 -1
- package/dist/config/feature-flags.js.map +1 -1
- package/dist/context/bootstrap-loader.d.ts +48 -0
- package/dist/context/bootstrap-loader.js +123 -0
- package/dist/context/bootstrap-loader.js.map +1 -0
- package/dist/context/codebase-rag/chunker.js +2 -2
- package/dist/context/codebase-rag/chunker.js.map +1 -1
- package/dist/copilot/copilot-proxy.d.ts +15 -1
- package/dist/copilot/copilot-proxy.js +92 -23
- package/dist/copilot/copilot-proxy.js.map +1 -1
- package/dist/daemon/health-monitor.js +11 -7
- package/dist/daemon/health-monitor.js.map +1 -1
- package/dist/daemon/heartbeat.d.ts +112 -0
- package/dist/daemon/heartbeat.js +339 -0
- package/dist/daemon/heartbeat.js.map +1 -0
- package/dist/desktop-automation/smart-snapshot.d.ts +11 -0
- package/dist/desktop-automation/smart-snapshot.js +38 -0
- package/dist/desktop-automation/smart-snapshot.js.map +1 -1
- package/dist/extensions/extension-loader.js +4 -0
- package/dist/extensions/extension-loader.js.map +1 -1
- package/dist/identity/identity-manager.d.ts +95 -0
- package/dist/identity/identity-manager.js +242 -0
- package/dist/identity/identity-manager.js.map +1 -0
- package/dist/index.js +147 -17
- package/dist/index.js.map +1 -1
- package/dist/input/text-to-speech.js +4 -2
- package/dist/input/text-to-speech.js.map +1 -1
- package/dist/input/voice-control.js +5 -3
- package/dist/input/voice-control.js.map +1 -1
- package/dist/integrations/github-integration.js +1 -1
- package/dist/integrations/github-integration.js.map +1 -1
- package/dist/orchestration/orchestrator.js +3 -0
- package/dist/orchestration/orchestrator.js.map +1 -1
- package/dist/persistence/conversation-branches.js +2 -1
- package/dist/persistence/conversation-branches.js.map +1 -1
- package/dist/persistence/session-store.d.ts +1 -1
- package/dist/persistence/session-store.js +1 -1
- package/dist/persistence/session-store.js.map +1 -1
- package/dist/plugins/plugin-system.js +5 -2
- package/dist/plugins/plugin-system.js.map +1 -1
- package/dist/providers/gemini-provider.js +6 -4
- package/dist/providers/gemini-provider.js.map +1 -1
- package/dist/providers/local-llm-provider.js +8 -0
- package/dist/providers/local-llm-provider.js.map +1 -1
- package/dist/sandbox/auto-sandbox.d.ts +59 -0
- package/dist/sandbox/auto-sandbox.js +145 -0
- package/dist/sandbox/auto-sandbox.js.map +1 -0
- package/dist/scheduler/cron-scheduler.js +2 -0
- package/dist/scheduler/cron-scheduler.js.map +1 -1
- package/dist/scheduler/scheduler.js +11 -2
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/security/audit-logger.d.ts +127 -0
- package/dist/security/audit-logger.js +194 -0
- package/dist/security/audit-logger.js.map +1 -0
- package/dist/security/bash-allowlist/allowlist-store.js +3 -2
- package/dist/security/bash-allowlist/allowlist-store.js.map +1 -1
- package/dist/security/bash-parser.js +0 -2
- package/dist/security/bash-parser.js.map +1 -1
- package/dist/security/code-validator.d.ts +51 -0
- package/dist/security/code-validator.js +185 -0
- package/dist/security/code-validator.js.map +1 -0
- package/dist/security/dangerous-patterns.d.ts +68 -0
- package/dist/security/dangerous-patterns.js +218 -0
- package/dist/security/dangerous-patterns.js.map +1 -0
- package/dist/security/remote-approval.d.ts +65 -0
- package/dist/security/remote-approval.js +138 -0
- package/dist/security/remote-approval.js.map +1 -0
- package/dist/security/security-audit.d.ts +7 -0
- package/dist/security/security-audit.js +23 -0
- package/dist/security/security-audit.js.map +1 -1
- package/dist/security/syntax-validator.d.ts +17 -0
- package/dist/security/syntax-validator.js +292 -0
- package/dist/security/syntax-validator.js.map +1 -0
- package/dist/server/index.js +277 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/logging.js +9 -1
- package/dist/server/middleware/logging.js.map +1 -1
- package/dist/server/routes/memory.js +4 -1
- package/dist/server/routes/memory.js.map +1 -1
- package/dist/server/routes/metrics.js +1 -1
- package/dist/server/routes/metrics.js.map +1 -1
- package/dist/server/routes/sessions.js +5 -4
- package/dist/server/routes/sessions.js.map +1 -1
- package/dist/server/websocket/handler.js +8 -2
- package/dist/server/websocket/handler.js.map +1 -1
- package/dist/services/prompt-builder.js +16 -0
- package/dist/services/prompt-builder.js.map +1 -1
- package/dist/skills/hub.d.ts +231 -0
- package/dist/skills/hub.js +694 -0
- package/dist/skills/hub.js.map +1 -0
- package/dist/skills/skill-loader.js +1 -1
- package/dist/skills/skill-loader.js.map +1 -1
- package/dist/skills/skill-manager.js +2 -1
- package/dist/skills/skill-manager.js.map +1 -1
- package/dist/skills/skill-registry.js +4 -0
- package/dist/skills/skill-registry.js.map +1 -1
- package/dist/talk-mode/providers/audioreader-tts.js +1 -0
- package/dist/talk-mode/providers/audioreader-tts.js.map +1 -1
- package/dist/tools/apply-patch.d.ts +1 -0
- package/dist/tools/apply-patch.js +66 -12
- package/dist/tools/apply-patch.js.map +1 -1
- package/dist/tools/bash/bash-tool.d.ts +123 -0
- package/dist/tools/bash/bash-tool.js +549 -0
- package/dist/tools/bash/bash-tool.js.map +1 -0
- package/dist/tools/bash/command-validator.d.ts +49 -0
- package/dist/tools/bash/command-validator.js +223 -0
- package/dist/tools/bash/command-validator.js.map +1 -0
- package/dist/tools/bash/index.d.ts +7 -0
- package/dist/tools/bash/index.js +8 -0
- package/dist/tools/bash/index.js.map +1 -0
- package/dist/tools/bash/security-patterns.d.ts +44 -0
- package/dist/tools/bash/security-patterns.js +234 -0
- package/dist/tools/bash/security-patterns.js.map +1 -0
- package/dist/tools/bash/streaming-executor.d.ts +23 -0
- package/dist/tools/bash/streaming-executor.js +134 -0
- package/dist/tools/bash/streaming-executor.js.map +1 -0
- package/dist/tools/bash.js +5 -3
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/code-formatter.js +41 -27
- package/dist/tools/code-formatter.js.map +1 -1
- package/dist/tools/code-review.js +1 -1
- package/dist/tools/code-review.js.map +1 -1
- package/dist/tools/computer-control-tool.js +21 -0
- package/dist/tools/computer-control-tool.js.map +1 -1
- package/dist/tools/document-tool.js +3 -2
- package/dist/tools/document-tool.js.map +1 -1
- package/dist/tools/git-tool.d.ts +45 -0
- package/dist/tools/git-tool.js +224 -2
- package/dist/tools/git-tool.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +1 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/morph-editor.js +1 -0
- package/dist/tools/morph-editor.js.map +1 -1
- package/dist/tools/multi-edit.js +31 -3
- package/dist/tools/multi-edit.js.map +1 -1
- package/dist/tools/notebook-tool.js +8 -2
- package/dist/tools/notebook-tool.js.map +1 -1
- package/dist/tools/process-tool.d.ts +69 -0
- package/dist/tools/process-tool.js +222 -0
- package/dist/tools/process-tool.js.map +1 -0
- package/dist/tools/registry/git-tools.d.ts +32 -0
- package/dist/tools/registry/git-tools.js +211 -0
- package/dist/tools/registry/git-tools.js.map +1 -0
- package/dist/tools/registry/index.d.ts +2 -0
- package/dist/tools/registry/index.js +8 -0
- package/dist/tools/registry/index.js.map +1 -1
- package/dist/tools/registry/misc-tools.d.ts +32 -4
- package/dist/tools/registry/misc-tools.js +230 -90
- package/dist/tools/registry/misc-tools.js.map +1 -1
- package/dist/tools/registry/process-tools.d.ts +20 -0
- package/dist/tools/registry/process-tools.js +141 -0
- package/dist/tools/registry/process-tools.js.map +1 -0
- package/dist/tools/registry/types.d.ts +2 -0
- package/dist/tools/search.js +4 -2
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/video-tool.js +30 -14
- package/dist/tools/video-tool.js.map +1 -1
- package/dist/tools/web-search.js +4 -1
- package/dist/tools/web-search.js.map +1 -1
- package/dist/ui/components/ChatInterface.js +9 -0
- package/dist/ui/components/ChatInterface.js.map +1 -1
- package/dist/utils/autonomy-manager.js +3 -2
- package/dist/utils/autonomy-manager.js.map +1 -1
- package/dist/utils/config-validation/schema.d.ts +15 -15
- package/dist/utils/confirmation-service.d.ts +16 -0
- package/dist/utils/confirmation-service.js +37 -3
- package/dist/utils/confirmation-service.js.map +1 -1
- package/dist/utils/custom-instructions.js +2 -1
- package/dist/utils/custom-instructions.js.map +1 -1
- package/dist/utils/diff-generator.js +3 -1
- package/dist/utils/diff-generator.js.map +1 -1
- package/dist/utils/graceful-shutdown.js +9 -9
- package/dist/utils/graceful-shutdown.js.map +1 -1
- package/dist/utils/head-tail-truncation.d.ts +18 -0
- package/dist/utils/head-tail-truncation.js +127 -0
- package/dist/utils/head-tail-truncation.js.map +1 -1
- package/dist/utils/history-manager.js +3 -2
- package/dist/utils/history-manager.js.map +1 -1
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +18 -3
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/performance.js +16 -15
- package/dist/utils/performance.js.map +1 -1
- package/dist/utils/stream-helpers.js +4 -2
- package/dist/utils/stream-helpers.js.map +1 -1
- package/dist/utils/update-notifier.js +2 -1
- package/dist/utils/update-notifier.js.map +1 -1
- package/dist/workflows/pipeline.d.ts +54 -1
- package/dist/workflows/pipeline.js +128 -7
- package/dist/workflows/pipeline.js.map +1 -1
- package/dist/workflows/step-manager.js +2 -1
- package/dist/workflows/step-manager.js.map +1 -1
- package/package.json +6 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health-monitor.js","sourceRoot":"","sources":["../../src/daemon/health-monitor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"health-monitor.js","sourceRoot":"","sources":["../../src/daemon/health-monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat Engine
|
|
3
|
+
*
|
|
4
|
+
* OpenClaw-inspired periodic wake system that reads a HEARTBEAT.md checklist
|
|
5
|
+
* and surfaces important items via agent review. Integrates with the existing
|
|
6
|
+
* CronAgentBridge pattern to create agent instances for checklist evaluation.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Configurable interval (default 30 minutes)
|
|
10
|
+
* - Active hours filtering (only fires during configured hours)
|
|
11
|
+
* - Smart suppression (HEARTBEAT_OK skips with counter)
|
|
12
|
+
* - Event-driven (heartbeat:wake, heartbeat:result, heartbeat:suppressed)
|
|
13
|
+
*/
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
15
|
+
export interface HeartbeatConfig {
|
|
16
|
+
/** Interval between heartbeat checks (ms). Default: 30 minutes */
|
|
17
|
+
intervalMs: number;
|
|
18
|
+
/** Start of active hours (0-23). Default: 8 */
|
|
19
|
+
activeHoursStart: number;
|
|
20
|
+
/** End of active hours (0-23). Default: 22 */
|
|
21
|
+
activeHoursEnd: number;
|
|
22
|
+
/** IANA timezone string. Default: system timezone */
|
|
23
|
+
timezone: string;
|
|
24
|
+
/** Path to HEARTBEAT.md checklist. Default: .codebuddy/HEARTBEAT.md */
|
|
25
|
+
heartbeatFilePath: string;
|
|
26
|
+
/** Keyword in agent response that suppresses action. Default: HEARTBEAT_OK */
|
|
27
|
+
suppressionKeyword: string;
|
|
28
|
+
/** Max consecutive suppressions before forcing a full review. Default: 5 */
|
|
29
|
+
maxConsecutiveSuppressions: number;
|
|
30
|
+
/** Whether the heartbeat engine is enabled. Default: true */
|
|
31
|
+
enabled: boolean;
|
|
32
|
+
/** Optional override for agent review (used in tests). */
|
|
33
|
+
agentReviewFn?: (checklistContent: string) => Promise<string>;
|
|
34
|
+
}
|
|
35
|
+
export interface HeartbeatStatus {
|
|
36
|
+
running: boolean;
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
lastRunTime: Date | null;
|
|
39
|
+
nextRunTime: Date | null;
|
|
40
|
+
consecutiveSuppressions: number;
|
|
41
|
+
totalTicks: number;
|
|
42
|
+
totalSuppressions: number;
|
|
43
|
+
lastResult: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface HeartbeatTickResult {
|
|
46
|
+
timestamp: Date;
|
|
47
|
+
skipped: boolean;
|
|
48
|
+
skipReason?: 'outside_active_hours' | 'disabled' | 'file_not_found';
|
|
49
|
+
suppressed: boolean;
|
|
50
|
+
agentResponse?: string;
|
|
51
|
+
checklistContent?: string;
|
|
52
|
+
duration: number;
|
|
53
|
+
}
|
|
54
|
+
export declare class HeartbeatEngine extends EventEmitter {
|
|
55
|
+
private config;
|
|
56
|
+
private timer;
|
|
57
|
+
private running;
|
|
58
|
+
private lastRunTime;
|
|
59
|
+
private nextRunTime;
|
|
60
|
+
private consecutiveSuppressions;
|
|
61
|
+
private totalTicks;
|
|
62
|
+
private totalSuppressions;
|
|
63
|
+
private lastResult;
|
|
64
|
+
constructor(config?: Partial<HeartbeatConfig>);
|
|
65
|
+
/**
|
|
66
|
+
* Start the heartbeat engine
|
|
67
|
+
*/
|
|
68
|
+
start(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Stop the heartbeat engine
|
|
71
|
+
*/
|
|
72
|
+
stop(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Schedule the next tick
|
|
75
|
+
*/
|
|
76
|
+
private scheduleNext;
|
|
77
|
+
/**
|
|
78
|
+
* Execute a single heartbeat tick
|
|
79
|
+
*
|
|
80
|
+
* Reads HEARTBEAT.md, creates an agent to review the checklist,
|
|
81
|
+
* and emits appropriate events based on the result.
|
|
82
|
+
*/
|
|
83
|
+
tick(): Promise<HeartbeatTickResult>;
|
|
84
|
+
/**
|
|
85
|
+
* Check if the current time is within configured active hours
|
|
86
|
+
*/
|
|
87
|
+
isWithinActiveHours(now?: Date): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Execute agent review of the heartbeat checklist
|
|
90
|
+
*
|
|
91
|
+
* Uses the same lazy-load agent pattern as CronAgentBridge.
|
|
92
|
+
*/
|
|
93
|
+
private executeAgentReview;
|
|
94
|
+
/**
|
|
95
|
+
* Get current heartbeat engine status
|
|
96
|
+
*/
|
|
97
|
+
getStatus(): HeartbeatStatus;
|
|
98
|
+
/**
|
|
99
|
+
* Get the current configuration (copy)
|
|
100
|
+
*/
|
|
101
|
+
getConfig(): HeartbeatConfig;
|
|
102
|
+
/**
|
|
103
|
+
* Update configuration (requires restart to take effect for interval changes)
|
|
104
|
+
*/
|
|
105
|
+
updateConfig(updates: Partial<HeartbeatConfig>): void;
|
|
106
|
+
/**
|
|
107
|
+
* Check if the engine is currently running
|
|
108
|
+
*/
|
|
109
|
+
isRunning(): boolean;
|
|
110
|
+
}
|
|
111
|
+
export declare function getHeartbeatEngine(config?: Partial<HeartbeatConfig>): HeartbeatEngine;
|
|
112
|
+
export declare function resetHeartbeatEngine(): void;
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat Engine
|
|
3
|
+
*
|
|
4
|
+
* OpenClaw-inspired periodic wake system that reads a HEARTBEAT.md checklist
|
|
5
|
+
* and surfaces important items via agent review. Integrates with the existing
|
|
6
|
+
* CronAgentBridge pattern to create agent instances for checklist evaluation.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Configurable interval (default 30 minutes)
|
|
10
|
+
* - Active hours filtering (only fires during configured hours)
|
|
11
|
+
* - Smart suppression (HEARTBEAT_OK skips with counter)
|
|
12
|
+
* - Event-driven (heartbeat:wake, heartbeat:result, heartbeat:suppressed)
|
|
13
|
+
*/
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
15
|
+
import * as fs from 'fs/promises';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { logger } from '../utils/logger.js';
|
|
18
|
+
const DEFAULT_HEARTBEAT_CONFIG = {
|
|
19
|
+
intervalMs: 30 * 60 * 1000, // 30 minutes
|
|
20
|
+
activeHoursStart: 8,
|
|
21
|
+
activeHoursEnd: 22,
|
|
22
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
23
|
+
heartbeatFilePath: path.join(process.cwd(), '.codebuddy', 'HEARTBEAT.md'),
|
|
24
|
+
suppressionKeyword: 'HEARTBEAT_OK',
|
|
25
|
+
maxConsecutiveSuppressions: 5,
|
|
26
|
+
enabled: true,
|
|
27
|
+
};
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Heartbeat Engine
|
|
30
|
+
// ============================================================================
|
|
31
|
+
export class HeartbeatEngine extends EventEmitter {
|
|
32
|
+
config;
|
|
33
|
+
timer = null;
|
|
34
|
+
running = false;
|
|
35
|
+
lastRunTime = null;
|
|
36
|
+
nextRunTime = null;
|
|
37
|
+
consecutiveSuppressions = 0;
|
|
38
|
+
totalTicks = 0;
|
|
39
|
+
totalSuppressions = 0;
|
|
40
|
+
lastResult = null;
|
|
41
|
+
constructor(config = {}) {
|
|
42
|
+
super();
|
|
43
|
+
this.config = { ...DEFAULT_HEARTBEAT_CONFIG, ...config };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Start the heartbeat engine
|
|
47
|
+
*/
|
|
48
|
+
start() {
|
|
49
|
+
if (this.running) {
|
|
50
|
+
logger.warn('Heartbeat engine already running');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!this.config.enabled) {
|
|
54
|
+
logger.info('Heartbeat engine is disabled');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this.running = true;
|
|
58
|
+
this.scheduleNext();
|
|
59
|
+
logger.info('Heartbeat engine started', {
|
|
60
|
+
intervalMs: this.config.intervalMs,
|
|
61
|
+
activeHours: `${this.config.activeHoursStart}-${this.config.activeHoursEnd}`,
|
|
62
|
+
timezone: this.config.timezone,
|
|
63
|
+
});
|
|
64
|
+
this.emit('started');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Stop the heartbeat engine
|
|
68
|
+
*/
|
|
69
|
+
stop() {
|
|
70
|
+
if (this.timer) {
|
|
71
|
+
clearTimeout(this.timer);
|
|
72
|
+
this.timer = null;
|
|
73
|
+
}
|
|
74
|
+
this.running = false;
|
|
75
|
+
this.nextRunTime = null;
|
|
76
|
+
logger.info('Heartbeat engine stopped');
|
|
77
|
+
this.emit('stopped');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Schedule the next tick
|
|
81
|
+
*/
|
|
82
|
+
scheduleNext() {
|
|
83
|
+
if (!this.running)
|
|
84
|
+
return;
|
|
85
|
+
// Clear any existing timer to prevent orphaned timers
|
|
86
|
+
if (this.timer) {
|
|
87
|
+
clearTimeout(this.timer);
|
|
88
|
+
}
|
|
89
|
+
this.nextRunTime = new Date(Date.now() + this.config.intervalMs);
|
|
90
|
+
this.timer = setTimeout(async () => {
|
|
91
|
+
try {
|
|
92
|
+
await this.tick();
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
logger.error('Heartbeat tick error', { error: String(error) });
|
|
96
|
+
this.emit('heartbeat:error', { error });
|
|
97
|
+
}
|
|
98
|
+
// Schedule next tick after completion
|
|
99
|
+
this.scheduleNext();
|
|
100
|
+
}, this.config.intervalMs);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Execute a single heartbeat tick
|
|
104
|
+
*
|
|
105
|
+
* Reads HEARTBEAT.md, creates an agent to review the checklist,
|
|
106
|
+
* and emits appropriate events based on the result.
|
|
107
|
+
*/
|
|
108
|
+
async tick() {
|
|
109
|
+
const startTime = Date.now();
|
|
110
|
+
this.totalTicks++;
|
|
111
|
+
// Check if enabled
|
|
112
|
+
if (!this.config.enabled) {
|
|
113
|
+
const result = {
|
|
114
|
+
timestamp: new Date(),
|
|
115
|
+
skipped: true,
|
|
116
|
+
skipReason: 'disabled',
|
|
117
|
+
suppressed: false,
|
|
118
|
+
duration: Date.now() - startTime,
|
|
119
|
+
};
|
|
120
|
+
logger.debug('Heartbeat tick skipped: disabled');
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
// Check active hours
|
|
124
|
+
if (!this.isWithinActiveHours()) {
|
|
125
|
+
const result = {
|
|
126
|
+
timestamp: new Date(),
|
|
127
|
+
skipped: true,
|
|
128
|
+
skipReason: 'outside_active_hours',
|
|
129
|
+
suppressed: false,
|
|
130
|
+
duration: Date.now() - startTime,
|
|
131
|
+
};
|
|
132
|
+
logger.debug('Heartbeat tick skipped: outside active hours');
|
|
133
|
+
this.emit('heartbeat:skipped', result);
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
// Read the heartbeat checklist
|
|
137
|
+
let checklistContent;
|
|
138
|
+
try {
|
|
139
|
+
checklistContent = await fs.readFile(this.config.heartbeatFilePath, 'utf-8');
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
const result = {
|
|
143
|
+
timestamp: new Date(),
|
|
144
|
+
skipped: true,
|
|
145
|
+
skipReason: 'file_not_found',
|
|
146
|
+
suppressed: false,
|
|
147
|
+
duration: Date.now() - startTime,
|
|
148
|
+
};
|
|
149
|
+
logger.warn('Heartbeat file not found', { path: this.config.heartbeatFilePath });
|
|
150
|
+
this.emit('heartbeat:skipped', result);
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
this.lastRunTime = new Date();
|
|
154
|
+
this.emit('heartbeat:wake', { timestamp: this.lastRunTime, checklistContent });
|
|
155
|
+
// Create agent instance to review checklist (same pattern as CronAgentBridge)
|
|
156
|
+
let agentResponse;
|
|
157
|
+
try {
|
|
158
|
+
agentResponse = await this.executeAgentReview(checklistContent);
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
logger.error('Heartbeat agent review failed', { error: String(error) });
|
|
162
|
+
const result = {
|
|
163
|
+
timestamp: new Date(),
|
|
164
|
+
skipped: false,
|
|
165
|
+
suppressed: false,
|
|
166
|
+
checklistContent,
|
|
167
|
+
agentResponse: `Error: ${String(error)}`,
|
|
168
|
+
duration: Date.now() - startTime,
|
|
169
|
+
};
|
|
170
|
+
this.emit('heartbeat:error', { error });
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
this.lastResult = agentResponse;
|
|
174
|
+
// Check for suppression keyword
|
|
175
|
+
const isSuppressed = agentResponse.includes(this.config.suppressionKeyword);
|
|
176
|
+
if (isSuppressed) {
|
|
177
|
+
this.consecutiveSuppressions++;
|
|
178
|
+
this.totalSuppressions++;
|
|
179
|
+
// If max consecutive suppressions reached, force a full review next time
|
|
180
|
+
if (this.consecutiveSuppressions >= this.config.maxConsecutiveSuppressions) {
|
|
181
|
+
logger.info('Max consecutive suppressions reached, resetting counter', {
|
|
182
|
+
count: this.consecutiveSuppressions,
|
|
183
|
+
});
|
|
184
|
+
this.consecutiveSuppressions = 0;
|
|
185
|
+
this.emit('heartbeat:suppression-limit', {
|
|
186
|
+
totalSuppressions: this.totalSuppressions,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const result = {
|
|
190
|
+
timestamp: new Date(),
|
|
191
|
+
skipped: false,
|
|
192
|
+
suppressed: true,
|
|
193
|
+
agentResponse,
|
|
194
|
+
checklistContent,
|
|
195
|
+
duration: Date.now() - startTime,
|
|
196
|
+
};
|
|
197
|
+
logger.debug('Heartbeat suppressed by agent', {
|
|
198
|
+
consecutiveSuppressions: this.consecutiveSuppressions,
|
|
199
|
+
});
|
|
200
|
+
this.emit('heartbeat:suppressed', {
|
|
201
|
+
consecutiveSuppressions: this.consecutiveSuppressions,
|
|
202
|
+
agentResponse,
|
|
203
|
+
});
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
// Agent found something noteworthy - reset suppression counter
|
|
207
|
+
this.consecutiveSuppressions = 0;
|
|
208
|
+
const result = {
|
|
209
|
+
timestamp: new Date(),
|
|
210
|
+
skipped: false,
|
|
211
|
+
suppressed: false,
|
|
212
|
+
agentResponse,
|
|
213
|
+
checklistContent,
|
|
214
|
+
duration: Date.now() - startTime,
|
|
215
|
+
};
|
|
216
|
+
this.emit('heartbeat:result', {
|
|
217
|
+
agentResponse,
|
|
218
|
+
checklistContent,
|
|
219
|
+
duration: result.duration,
|
|
220
|
+
});
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Check if the current time is within configured active hours
|
|
225
|
+
*/
|
|
226
|
+
isWithinActiveHours(now) {
|
|
227
|
+
const date = now || new Date();
|
|
228
|
+
// Get the hour in the configured timezone
|
|
229
|
+
let hour;
|
|
230
|
+
try {
|
|
231
|
+
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
232
|
+
hour: 'numeric',
|
|
233
|
+
hourCycle: 'h23',
|
|
234
|
+
timeZone: this.config.timezone,
|
|
235
|
+
});
|
|
236
|
+
hour = parseInt(formatter.format(date), 10);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Fallback to local time if timezone is invalid
|
|
240
|
+
hour = date.getHours();
|
|
241
|
+
}
|
|
242
|
+
const { activeHoursStart, activeHoursEnd } = this.config;
|
|
243
|
+
// Handle wrap-around (e.g., activeHoursStart=22, activeHoursEnd=6)
|
|
244
|
+
if (activeHoursStart <= activeHoursEnd) {
|
|
245
|
+
return hour >= activeHoursStart && hour < activeHoursEnd;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
return hour >= activeHoursStart || hour < activeHoursEnd;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Execute agent review of the heartbeat checklist
|
|
253
|
+
*
|
|
254
|
+
* Uses the same lazy-load agent pattern as CronAgentBridge.
|
|
255
|
+
*/
|
|
256
|
+
async executeAgentReview(checklistContent) {
|
|
257
|
+
// Allow override for testing
|
|
258
|
+
if (this.config.agentReviewFn) {
|
|
259
|
+
return this.config.agentReviewFn(checklistContent);
|
|
260
|
+
}
|
|
261
|
+
const apiKey = process.env.GROK_API_KEY || '';
|
|
262
|
+
const baseURL = process.env.GROK_BASE_URL;
|
|
263
|
+
const model = process.env.GROK_MODEL;
|
|
264
|
+
const forceReview = this.consecutiveSuppressions >= this.config.maxConsecutiveSuppressions - 1;
|
|
265
|
+
const suppressionContext = forceReview
|
|
266
|
+
? `\n\nIMPORTANT: There have been ${this.consecutiveSuppressions} consecutive suppressions. Please do a thorough review even if everything looks fine.`
|
|
267
|
+
: '';
|
|
268
|
+
const prompt = [
|
|
269
|
+
'You are a heartbeat monitor reviewing a project checklist.',
|
|
270
|
+
'Review the following HEARTBEAT.md checklist and determine if any items need attention.',
|
|
271
|
+
'',
|
|
272
|
+
`If everything looks fine, respond with exactly: ${this.config.suppressionKeyword}`,
|
|
273
|
+
'If any items need attention, describe what needs to be done.',
|
|
274
|
+
suppressionContext,
|
|
275
|
+
'',
|
|
276
|
+
'---',
|
|
277
|
+
checklistContent,
|
|
278
|
+
].join('\n');
|
|
279
|
+
// Lazy load agent to avoid circular deps
|
|
280
|
+
const { CodeBuddyAgent } = await import('../agent/codebuddy-agent.js');
|
|
281
|
+
const agent = new CodeBuddyAgent(apiKey, baseURL, model, 10, // limited tool rounds for heartbeat review
|
|
282
|
+
false // no RAG for heartbeat
|
|
283
|
+
);
|
|
284
|
+
const entries = await agent.processUserMessage(prompt);
|
|
285
|
+
const assistantEntries = entries.filter(e => e.type === 'assistant');
|
|
286
|
+
return assistantEntries.map(e => e.content).join('\n') || 'No response';
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Get current heartbeat engine status
|
|
290
|
+
*/
|
|
291
|
+
getStatus() {
|
|
292
|
+
return {
|
|
293
|
+
running: this.running,
|
|
294
|
+
enabled: this.config.enabled,
|
|
295
|
+
lastRunTime: this.lastRunTime,
|
|
296
|
+
nextRunTime: this.nextRunTime,
|
|
297
|
+
consecutiveSuppressions: this.consecutiveSuppressions,
|
|
298
|
+
totalTicks: this.totalTicks,
|
|
299
|
+
totalSuppressions: this.totalSuppressions,
|
|
300
|
+
lastResult: this.lastResult,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Get the current configuration (copy)
|
|
305
|
+
*/
|
|
306
|
+
getConfig() {
|
|
307
|
+
return { ...this.config };
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Update configuration (requires restart to take effect for interval changes)
|
|
311
|
+
*/
|
|
312
|
+
updateConfig(updates) {
|
|
313
|
+
this.config = { ...this.config, ...updates };
|
|
314
|
+
logger.info('Heartbeat config updated', { updates: Object.keys(updates) });
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Check if the engine is currently running
|
|
318
|
+
*/
|
|
319
|
+
isRunning() {
|
|
320
|
+
return this.running;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// ============================================================================
|
|
324
|
+
// Singleton
|
|
325
|
+
// ============================================================================
|
|
326
|
+
let heartbeatInstance = null;
|
|
327
|
+
export function getHeartbeatEngine(config) {
|
|
328
|
+
if (!heartbeatInstance) {
|
|
329
|
+
heartbeatInstance = new HeartbeatEngine(config);
|
|
330
|
+
}
|
|
331
|
+
return heartbeatInstance;
|
|
332
|
+
}
|
|
333
|
+
export function resetHeartbeatEngine() {
|
|
334
|
+
if (heartbeatInstance) {
|
|
335
|
+
heartbeatInstance.stop();
|
|
336
|
+
}
|
|
337
|
+
heartbeatInstance = null;
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/daemon/heartbeat.ts"],"names":[],"mappings":"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"}
|
|
@@ -129,6 +129,17 @@ export declare class SmartSnapshotManager extends EventEmitter {
|
|
|
129
129
|
* Take a snapshot of the current screen/window
|
|
130
130
|
*/
|
|
131
131
|
takeSnapshot(options?: SnapshotOptions): Promise<Snapshot>;
|
|
132
|
+
/**
|
|
133
|
+
* Get the next available ref number.
|
|
134
|
+
* Allows external modules (e.g. browser-automation) to share the global ref space
|
|
135
|
+
* so desktop and browser refs never collide.
|
|
136
|
+
*/
|
|
137
|
+
getNextRef(): number;
|
|
138
|
+
/**
|
|
139
|
+
* Inject browser-sourced elements into the current snapshot.
|
|
140
|
+
* This allows unified ref lookup across desktop and browser elements.
|
|
141
|
+
*/
|
|
142
|
+
injectBrowserElements(elements: UIElement[], source?: string): void;
|
|
132
143
|
/**
|
|
133
144
|
* Get element by reference number
|
|
134
145
|
*/
|
|
@@ -114,6 +114,34 @@ export class SmartSnapshotManager extends EventEmitter {
|
|
|
114
114
|
throw error;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Get the next available ref number.
|
|
119
|
+
* Allows external modules (e.g. browser-automation) to share the global ref space
|
|
120
|
+
* so desktop and browser refs never collide.
|
|
121
|
+
*/
|
|
122
|
+
getNextRef() {
|
|
123
|
+
return this.nextRef++;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Inject browser-sourced elements into the current snapshot.
|
|
127
|
+
* This allows unified ref lookup across desktop and browser elements.
|
|
128
|
+
*/
|
|
129
|
+
injectBrowserElements(elements, source = 'browser-accessibility') {
|
|
130
|
+
if (!this.currentSnapshot?.valid) {
|
|
131
|
+
logger.warn('Cannot inject browser elements: no valid snapshot');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
for (const elem of elements) {
|
|
135
|
+
// Tag element with browser source
|
|
136
|
+
elem.attributes = { ...elem.attributes, source };
|
|
137
|
+
this.currentSnapshot.elements.push(elem);
|
|
138
|
+
this.currentSnapshot.elementMap.set(elem.ref, elem);
|
|
139
|
+
}
|
|
140
|
+
logger.debug('Injected browser elements into desktop snapshot', {
|
|
141
|
+
count: elements.length,
|
|
142
|
+
source,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
117
145
|
/**
|
|
118
146
|
* Get element by reference number
|
|
119
147
|
*/
|
|
@@ -351,6 +379,11 @@ export class SmartSnapshotManager extends EventEmitter {
|
|
|
351
379
|
unlinkSync(outputPath);
|
|
352
380
|
}
|
|
353
381
|
catch (_e) { /* ignore */ }
|
|
382
|
+
try {
|
|
383
|
+
const { rmdirSync } = await import('fs');
|
|
384
|
+
rmdirSync(tmpDir);
|
|
385
|
+
}
|
|
386
|
+
catch (_e) { /* ignore */ }
|
|
354
387
|
return {
|
|
355
388
|
image: buf.toString('base64'),
|
|
356
389
|
format: 'png',
|
|
@@ -360,6 +393,11 @@ export class SmartSnapshotManager extends EventEmitter {
|
|
|
360
393
|
};
|
|
361
394
|
}
|
|
362
395
|
catch (_err) {
|
|
396
|
+
try {
|
|
397
|
+
const { rmSync } = await import('fs');
|
|
398
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
399
|
+
}
|
|
400
|
+
catch (_e) { /* ignore */ }
|
|
363
401
|
return null;
|
|
364
402
|
}
|
|
365
403
|
}
|