@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
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline Queue
|
|
3
|
+
*
|
|
4
|
+
* Buffers outbound messages when a channel is disconnected.
|
|
5
|
+
* Messages can be drained and sent when the channel reconnects.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - FIFO message buffering
|
|
9
|
+
* - Configurable maximum queue size
|
|
10
|
+
* - Oldest messages dropped when queue is full
|
|
11
|
+
* - Drain returns all queued messages in order
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A queued message waiting to be delivered
|
|
15
|
+
*/
|
|
16
|
+
export interface QueuedMessage {
|
|
17
|
+
/** Target channel/conversation ID */
|
|
18
|
+
channelId: string;
|
|
19
|
+
/** Message content */
|
|
20
|
+
content: string;
|
|
21
|
+
/** Optional metadata */
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
23
|
+
/** Timestamp when the message was queued */
|
|
24
|
+
queuedAt: Date;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Buffers messages for later delivery when a channel is offline.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const queue = new OfflineQueue(50);
|
|
32
|
+
*
|
|
33
|
+
* // When disconnected, queue outgoing messages
|
|
34
|
+
* queue.enqueue({ channelId: '123', content: 'Hello' });
|
|
35
|
+
*
|
|
36
|
+
* // When reconnected, drain and send
|
|
37
|
+
* const messages = queue.drain();
|
|
38
|
+
* for (const msg of messages) {
|
|
39
|
+
* await channel.send(msg);
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare class OfflineQueue {
|
|
44
|
+
private readonly maxSize;
|
|
45
|
+
private queue;
|
|
46
|
+
/**
|
|
47
|
+
* @param maxSize - Maximum number of messages to buffer (default: 100).
|
|
48
|
+
* When exceeded, oldest messages are dropped.
|
|
49
|
+
*/
|
|
50
|
+
constructor(maxSize?: number);
|
|
51
|
+
/**
|
|
52
|
+
* Queue a message for later delivery.
|
|
53
|
+
*
|
|
54
|
+
* @param message - The message to enqueue (channelId, content, optional metadata)
|
|
55
|
+
* @returns true if the message was queued, false if it replaced an older message
|
|
56
|
+
*/
|
|
57
|
+
enqueue(message: {
|
|
58
|
+
channelId: string;
|
|
59
|
+
content: string;
|
|
60
|
+
metadata?: Record<string, unknown>;
|
|
61
|
+
}): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Drain all queued messages.
|
|
64
|
+
*
|
|
65
|
+
* Returns all queued messages in FIFO order and clears the queue.
|
|
66
|
+
*/
|
|
67
|
+
drain(): QueuedMessage[];
|
|
68
|
+
/**
|
|
69
|
+
* Get the current queue size.
|
|
70
|
+
*/
|
|
71
|
+
size(): number;
|
|
72
|
+
/**
|
|
73
|
+
* Clear all queued messages without returning them.
|
|
74
|
+
*/
|
|
75
|
+
clear(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Peek at the next message without removing it.
|
|
78
|
+
*/
|
|
79
|
+
peek(): QueuedMessage | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Check if the queue is empty.
|
|
82
|
+
*/
|
|
83
|
+
isEmpty(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Check if the queue is full.
|
|
86
|
+
*/
|
|
87
|
+
isFull(): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Get the maximum queue size.
|
|
90
|
+
*/
|
|
91
|
+
getMaxSize(): number;
|
|
92
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline Queue
|
|
3
|
+
*
|
|
4
|
+
* Buffers outbound messages when a channel is disconnected.
|
|
5
|
+
* Messages can be drained and sent when the channel reconnects.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - FIFO message buffering
|
|
9
|
+
* - Configurable maximum queue size
|
|
10
|
+
* - Oldest messages dropped when queue is full
|
|
11
|
+
* - Drain returns all queued messages in order
|
|
12
|
+
*/
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Implementation
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Buffers messages for later delivery when a channel is offline.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const queue = new OfflineQueue(50);
|
|
22
|
+
*
|
|
23
|
+
* // When disconnected, queue outgoing messages
|
|
24
|
+
* queue.enqueue({ channelId: '123', content: 'Hello' });
|
|
25
|
+
*
|
|
26
|
+
* // When reconnected, drain and send
|
|
27
|
+
* const messages = queue.drain();
|
|
28
|
+
* for (const msg of messages) {
|
|
29
|
+
* await channel.send(msg);
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class OfflineQueue {
|
|
34
|
+
maxSize;
|
|
35
|
+
queue = [];
|
|
36
|
+
/**
|
|
37
|
+
* @param maxSize - Maximum number of messages to buffer (default: 100).
|
|
38
|
+
* When exceeded, oldest messages are dropped.
|
|
39
|
+
*/
|
|
40
|
+
constructor(maxSize = 100) {
|
|
41
|
+
this.maxSize = Math.max(1, maxSize);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Queue a message for later delivery.
|
|
45
|
+
*
|
|
46
|
+
* @param message - The message to enqueue (channelId, content, optional metadata)
|
|
47
|
+
* @returns true if the message was queued, false if it replaced an older message
|
|
48
|
+
*/
|
|
49
|
+
enqueue(message) {
|
|
50
|
+
const entry = {
|
|
51
|
+
channelId: message.channelId,
|
|
52
|
+
content: message.content,
|
|
53
|
+
metadata: message.metadata,
|
|
54
|
+
queuedAt: new Date(),
|
|
55
|
+
};
|
|
56
|
+
if (this.queue.length >= this.maxSize) {
|
|
57
|
+
// Drop oldest message to make room
|
|
58
|
+
this.queue.shift();
|
|
59
|
+
this.queue.push(entry);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
this.queue.push(entry);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Drain all queued messages.
|
|
67
|
+
*
|
|
68
|
+
* Returns all queued messages in FIFO order and clears the queue.
|
|
69
|
+
*/
|
|
70
|
+
drain() {
|
|
71
|
+
const messages = this.queue;
|
|
72
|
+
this.queue = [];
|
|
73
|
+
return messages;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get the current queue size.
|
|
77
|
+
*/
|
|
78
|
+
size() {
|
|
79
|
+
return this.queue.length;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clear all queued messages without returning them.
|
|
83
|
+
*/
|
|
84
|
+
clear() {
|
|
85
|
+
this.queue = [];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Peek at the next message without removing it.
|
|
89
|
+
*/
|
|
90
|
+
peek() {
|
|
91
|
+
return this.queue[0];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if the queue is empty.
|
|
95
|
+
*/
|
|
96
|
+
isEmpty() {
|
|
97
|
+
return this.queue.length === 0;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if the queue is full.
|
|
101
|
+
*/
|
|
102
|
+
isFull() {
|
|
103
|
+
return this.queue.length >= this.maxSize;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get the maximum queue size.
|
|
107
|
+
*/
|
|
108
|
+
getMaxSize() {
|
|
109
|
+
return this.maxSize;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=offline-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offline-queue.js","sourceRoot":"","sources":["../../src/channels/offline-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAoBH,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,YAAY;IACN,OAAO,CAAS;IACzB,KAAK,GAAoB,EAAE,CAAC;IAEpC;;;OAGG;IACH,YAAY,OAAO,GAAG,GAAG;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,OAIP;QACC,MAAM,KAAK,GAAkB;YAC3B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,QAAQ,EAAE,IAAI,IAAI,EAAE;SACrB,CAAC;QAEF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACtC,mCAAmC;YACnC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,KAAK;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reconnection Manager
|
|
3
|
+
*
|
|
4
|
+
* A shared reconnection utility with exponential backoff for channel adapters.
|
|
5
|
+
* Provides consistent reconnection behavior across all channel implementations.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Exponential backoff with configurable multiplier
|
|
9
|
+
* - Random jitter to prevent thundering herd
|
|
10
|
+
* - Maximum retry limit with exhaustion detection
|
|
11
|
+
* - Event-based notification of state changes
|
|
12
|
+
* - Cancellation support for pending reconnections
|
|
13
|
+
*/
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for reconnection behavior
|
|
17
|
+
*/
|
|
18
|
+
export interface ReconnectionConfig {
|
|
19
|
+
/** Maximum number of retry attempts before giving up (default: 10) */
|
|
20
|
+
maxRetries: number;
|
|
21
|
+
/** Initial delay in milliseconds before the first retry (default: 1000) */
|
|
22
|
+
initialDelayMs: number;
|
|
23
|
+
/** Maximum delay in milliseconds between retries (default: 60000) */
|
|
24
|
+
maxDelayMs: number;
|
|
25
|
+
/** Multiplier applied to delay after each retry (default: 2) */
|
|
26
|
+
backoffMultiplier: number;
|
|
27
|
+
/** Random jitter in milliseconds added to delay (default: 500) */
|
|
28
|
+
jitterMs: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Events emitted by the ReconnectionManager
|
|
32
|
+
*/
|
|
33
|
+
export interface ReconnectionEvents {
|
|
34
|
+
/** Emitted when a reconnection attempt is about to start */
|
|
35
|
+
reconnecting: (attempt: number, delayMs: number) => void;
|
|
36
|
+
/** Emitted when a reconnection attempt succeeds */
|
|
37
|
+
reconnected: (attempt: number) => void;
|
|
38
|
+
/** Emitted when all retry attempts are exhausted */
|
|
39
|
+
exhausted: (totalAttempts: number) => void;
|
|
40
|
+
/** Emitted when a reconnection attempt fails */
|
|
41
|
+
error: (error: Error, attempt: number) => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Manages reconnection attempts with exponential backoff for a named channel.
|
|
45
|
+
*
|
|
46
|
+
* Usage:
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const reconnector = new ReconnectionManager('discord');
|
|
49
|
+
*
|
|
50
|
+
* // On connection loss
|
|
51
|
+
* reconnector.scheduleReconnect(async () => {
|
|
52
|
+
* await channel.connect();
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* // On successful connection
|
|
56
|
+
* reconnector.onConnected();
|
|
57
|
+
*
|
|
58
|
+
* // On shutdown
|
|
59
|
+
* reconnector.cancel();
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare class ReconnectionManager extends EventEmitter {
|
|
63
|
+
private readonly name;
|
|
64
|
+
private readonly config;
|
|
65
|
+
private retryCount;
|
|
66
|
+
private pendingTimer;
|
|
67
|
+
private active;
|
|
68
|
+
constructor(name: string, config?: Partial<ReconnectionConfig>);
|
|
69
|
+
/**
|
|
70
|
+
* Schedule a reconnection attempt.
|
|
71
|
+
*
|
|
72
|
+
* Calculates the appropriate delay using exponential backoff with jitter
|
|
73
|
+
* and schedules the provided connect function. If max retries have been
|
|
74
|
+
* exceeded, emits the 'exhausted' event instead.
|
|
75
|
+
*
|
|
76
|
+
* @param connectFn - Async function that performs the connection attempt
|
|
77
|
+
*/
|
|
78
|
+
scheduleReconnect(connectFn: () => Promise<void>): void;
|
|
79
|
+
/**
|
|
80
|
+
* Reset retry counter on successful connection.
|
|
81
|
+
*
|
|
82
|
+
* Call this when the channel has successfully connected
|
|
83
|
+
* (whether from an initial connect or a reconnection attempt).
|
|
84
|
+
*/
|
|
85
|
+
onConnected(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Check if maximum retries have been exceeded.
|
|
88
|
+
*/
|
|
89
|
+
isExhausted(): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Get current retry count.
|
|
92
|
+
*/
|
|
93
|
+
getRetryCount(): number;
|
|
94
|
+
/**
|
|
95
|
+
* Cancel any pending reconnection attempt.
|
|
96
|
+
*/
|
|
97
|
+
cancel(): void;
|
|
98
|
+
/**
|
|
99
|
+
* Get the delay for the next retry attempt.
|
|
100
|
+
*
|
|
101
|
+
* Uses exponential backoff: initialDelay * multiplier^(retryCount-1)
|
|
102
|
+
* Capped at maxDelayMs. Adds random jitter.
|
|
103
|
+
*/
|
|
104
|
+
getCurrentDelay(): number;
|
|
105
|
+
/**
|
|
106
|
+
* Check if a reconnection is currently pending.
|
|
107
|
+
*/
|
|
108
|
+
isPending(): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Get the channel name this manager is for.
|
|
111
|
+
*/
|
|
112
|
+
getName(): string;
|
|
113
|
+
/**
|
|
114
|
+
* Get the current configuration.
|
|
115
|
+
*/
|
|
116
|
+
getConfig(): Readonly<ReconnectionConfig>;
|
|
117
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reconnection Manager
|
|
3
|
+
*
|
|
4
|
+
* A shared reconnection utility with exponential backoff for channel adapters.
|
|
5
|
+
* Provides consistent reconnection behavior across all channel implementations.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Exponential backoff with configurable multiplier
|
|
9
|
+
* - Random jitter to prevent thundering herd
|
|
10
|
+
* - Maximum retry limit with exhaustion detection
|
|
11
|
+
* - Event-based notification of state changes
|
|
12
|
+
* - Cancellation support for pending reconnections
|
|
13
|
+
*/
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
15
|
+
import { logger } from '../utils/logger.js';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Default Configuration
|
|
18
|
+
// ============================================================================
|
|
19
|
+
const DEFAULT_CONFIG = {
|
|
20
|
+
maxRetries: 10,
|
|
21
|
+
initialDelayMs: 1000,
|
|
22
|
+
maxDelayMs: 60000,
|
|
23
|
+
backoffMultiplier: 2,
|
|
24
|
+
jitterMs: 500,
|
|
25
|
+
};
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Implementation
|
|
28
|
+
// ============================================================================
|
|
29
|
+
/**
|
|
30
|
+
* Manages reconnection attempts with exponential backoff for a named channel.
|
|
31
|
+
*
|
|
32
|
+
* Usage:
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const reconnector = new ReconnectionManager('discord');
|
|
35
|
+
*
|
|
36
|
+
* // On connection loss
|
|
37
|
+
* reconnector.scheduleReconnect(async () => {
|
|
38
|
+
* await channel.connect();
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* // On successful connection
|
|
42
|
+
* reconnector.onConnected();
|
|
43
|
+
*
|
|
44
|
+
* // On shutdown
|
|
45
|
+
* reconnector.cancel();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export class ReconnectionManager extends EventEmitter {
|
|
49
|
+
name;
|
|
50
|
+
config;
|
|
51
|
+
retryCount = 0;
|
|
52
|
+
pendingTimer = null;
|
|
53
|
+
active = false;
|
|
54
|
+
constructor(name, config) {
|
|
55
|
+
super();
|
|
56
|
+
this.name = name;
|
|
57
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Schedule a reconnection attempt.
|
|
61
|
+
*
|
|
62
|
+
* Calculates the appropriate delay using exponential backoff with jitter
|
|
63
|
+
* and schedules the provided connect function. If max retries have been
|
|
64
|
+
* exceeded, emits the 'exhausted' event instead.
|
|
65
|
+
*
|
|
66
|
+
* @param connectFn - Async function that performs the connection attempt
|
|
67
|
+
*/
|
|
68
|
+
scheduleReconnect(connectFn) {
|
|
69
|
+
// Prevent concurrent reconnection schedules
|
|
70
|
+
if (this.active)
|
|
71
|
+
return;
|
|
72
|
+
if (this.isExhausted()) {
|
|
73
|
+
logger.debug(`${this.name}: reconnection exhausted after ${this.retryCount} attempts`);
|
|
74
|
+
this.emit('exhausted', this.retryCount);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.retryCount++;
|
|
78
|
+
const delay = this.getCurrentDelay();
|
|
79
|
+
this.active = true;
|
|
80
|
+
logger.debug(`${this.name}: scheduling reconnect attempt ${this.retryCount}/${this.config.maxRetries} in ${delay}ms`);
|
|
81
|
+
this.emit('reconnecting', this.retryCount, delay);
|
|
82
|
+
this.pendingTimer = setTimeout(async () => {
|
|
83
|
+
this.pendingTimer = null;
|
|
84
|
+
try {
|
|
85
|
+
await connectFn();
|
|
86
|
+
// If connectFn succeeds without throwing, emit reconnected
|
|
87
|
+
this.emit('reconnected', this.retryCount);
|
|
88
|
+
// Note: caller should call onConnected() to reset the state
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
92
|
+
logger.debug(`${this.name}: reconnect attempt ${this.retryCount} failed`, {
|
|
93
|
+
error: error.message,
|
|
94
|
+
});
|
|
95
|
+
this.emit('error', error, this.retryCount);
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
this.active = false;
|
|
99
|
+
}
|
|
100
|
+
}, delay);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Reset retry counter on successful connection.
|
|
104
|
+
*
|
|
105
|
+
* Call this when the channel has successfully connected
|
|
106
|
+
* (whether from an initial connect or a reconnection attempt).
|
|
107
|
+
*/
|
|
108
|
+
onConnected() {
|
|
109
|
+
this.retryCount = 0;
|
|
110
|
+
this.active = false;
|
|
111
|
+
if (this.pendingTimer) {
|
|
112
|
+
clearTimeout(this.pendingTimer);
|
|
113
|
+
this.pendingTimer = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if maximum retries have been exceeded.
|
|
118
|
+
*/
|
|
119
|
+
isExhausted() {
|
|
120
|
+
return this.retryCount >= this.config.maxRetries;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get current retry count.
|
|
124
|
+
*/
|
|
125
|
+
getRetryCount() {
|
|
126
|
+
return this.retryCount;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Cancel any pending reconnection attempt.
|
|
130
|
+
*/
|
|
131
|
+
cancel() {
|
|
132
|
+
this.active = false;
|
|
133
|
+
if (this.pendingTimer) {
|
|
134
|
+
clearTimeout(this.pendingTimer);
|
|
135
|
+
this.pendingTimer = null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get the delay for the next retry attempt.
|
|
140
|
+
*
|
|
141
|
+
* Uses exponential backoff: initialDelay * multiplier^(retryCount-1)
|
|
142
|
+
* Capped at maxDelayMs. Adds random jitter.
|
|
143
|
+
*/
|
|
144
|
+
getCurrentDelay() {
|
|
145
|
+
const exponentialDelay = this.config.initialDelayMs *
|
|
146
|
+
Math.pow(this.config.backoffMultiplier, Math.max(0, this.retryCount - 1));
|
|
147
|
+
const cappedDelay = Math.min(exponentialDelay, this.config.maxDelayMs);
|
|
148
|
+
// Add random jitter: [0, jitterMs)
|
|
149
|
+
const jitter = Math.floor(Math.random() * this.config.jitterMs);
|
|
150
|
+
return cappedDelay + jitter;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if a reconnection is currently pending.
|
|
154
|
+
*/
|
|
155
|
+
isPending() {
|
|
156
|
+
return this.active || this.pendingTimer !== null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get the channel name this manager is for.
|
|
160
|
+
*/
|
|
161
|
+
getName() {
|
|
162
|
+
return this.name;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get the current configuration.
|
|
166
|
+
*/
|
|
167
|
+
getConfig() {
|
|
168
|
+
return { ...this.config };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=reconnection-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnection-manager.js","sourceRoot":"","sources":["../../src/channels/reconnection-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal Channel Adapter
|
|
3
|
+
*
|
|
4
|
+
* Signal integration via signal-cli REST API.
|
|
5
|
+
* Requires a running signal-cli-rest-api instance
|
|
6
|
+
* (https://github.com/bbernhard/signal-cli-rest-api).
|
|
7
|
+
*
|
|
8
|
+
* Supports text messages, attachments, group messaging,
|
|
9
|
+
* and message reactions via the REST API.
|
|
10
|
+
*/
|
|
11
|
+
import type { ChannelConfig, OutboundMessage, DeliveryResult } from '../index.js';
|
|
12
|
+
import { BaseChannel } from '../index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Signal-specific configuration
|
|
15
|
+
*/
|
|
16
|
+
export interface SignalConfig extends ChannelConfig {
|
|
17
|
+
type: 'signal';
|
|
18
|
+
/** signal-cli REST API base URL (default: http://localhost:8080) */
|
|
19
|
+
apiUrl?: string;
|
|
20
|
+
/** Phone number registered with signal-cli (with country code, e.g. +1234567890) */
|
|
21
|
+
phoneNumber: string;
|
|
22
|
+
/** Polling interval in ms for receiving messages (default: 2000) */
|
|
23
|
+
pollInterval?: number;
|
|
24
|
+
/** Trust all known identities (skip safety number verification) */
|
|
25
|
+
trustAllIdentities?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Signal message from the REST API
|
|
29
|
+
*/
|
|
30
|
+
export interface SignalMessage {
|
|
31
|
+
envelope: {
|
|
32
|
+
source?: string;
|
|
33
|
+
sourceNumber?: string;
|
|
34
|
+
sourceName?: string;
|
|
35
|
+
sourceUuid?: string;
|
|
36
|
+
timestamp?: number;
|
|
37
|
+
dataMessage?: {
|
|
38
|
+
timestamp?: number;
|
|
39
|
+
message?: string;
|
|
40
|
+
expiresInSeconds?: number;
|
|
41
|
+
groupInfo?: {
|
|
42
|
+
groupId: string;
|
|
43
|
+
type?: string;
|
|
44
|
+
};
|
|
45
|
+
attachments?: SignalAttachment[];
|
|
46
|
+
quote?: {
|
|
47
|
+
id: number;
|
|
48
|
+
author: string;
|
|
49
|
+
text: string;
|
|
50
|
+
};
|
|
51
|
+
reaction?: {
|
|
52
|
+
emoji: string;
|
|
53
|
+
targetAuthor: string;
|
|
54
|
+
targetSentTimestamp: number;
|
|
55
|
+
isRemove: boolean;
|
|
56
|
+
};
|
|
57
|
+
mentions?: Array<{
|
|
58
|
+
start: number;
|
|
59
|
+
length: number;
|
|
60
|
+
uuid: string;
|
|
61
|
+
}>;
|
|
62
|
+
};
|
|
63
|
+
typingMessage?: {
|
|
64
|
+
action: 'STARTED' | 'STOPPED';
|
|
65
|
+
timestamp: number;
|
|
66
|
+
groupId?: string;
|
|
67
|
+
};
|
|
68
|
+
receiptMessage?: {
|
|
69
|
+
type: 'DELIVERY' | 'READ';
|
|
70
|
+
timestamps: number[];
|
|
71
|
+
};
|
|
72
|
+
syncMessage?: {
|
|
73
|
+
sentMessage?: {
|
|
74
|
+
destination?: string;
|
|
75
|
+
timestamp?: number;
|
|
76
|
+
message?: string;
|
|
77
|
+
groupInfo?: {
|
|
78
|
+
groupId: string;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
account?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Signal attachment
|
|
87
|
+
*/
|
|
88
|
+
export interface SignalAttachment {
|
|
89
|
+
contentType?: string;
|
|
90
|
+
filename?: string;
|
|
91
|
+
id?: string;
|
|
92
|
+
size?: number;
|
|
93
|
+
width?: number;
|
|
94
|
+
height?: number;
|
|
95
|
+
caption?: string;
|
|
96
|
+
voiceNote?: boolean;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Signal group info from the REST API
|
|
100
|
+
*/
|
|
101
|
+
export interface SignalGroup {
|
|
102
|
+
id: string;
|
|
103
|
+
name: string;
|
|
104
|
+
description?: string;
|
|
105
|
+
members: string[];
|
|
106
|
+
admins?: string[];
|
|
107
|
+
blocked?: boolean;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Signal channel via signal-cli REST API
|
|
111
|
+
*/
|
|
112
|
+
export declare class SignalChannel extends BaseChannel {
|
|
113
|
+
private pollTimer;
|
|
114
|
+
private polling;
|
|
115
|
+
private groupCache;
|
|
116
|
+
private reconnectionManager;
|
|
117
|
+
private consecutiveErrors;
|
|
118
|
+
constructor(config: SignalConfig);
|
|
119
|
+
private get signalConfig();
|
|
120
|
+
private get apiBase();
|
|
121
|
+
private get encodedNumber();
|
|
122
|
+
/**
|
|
123
|
+
* Make a request to the signal-cli REST API
|
|
124
|
+
*/
|
|
125
|
+
private apiRequest;
|
|
126
|
+
/**
|
|
127
|
+
* Connect to Signal by verifying the phone number is registered
|
|
128
|
+
* and starting the message polling loop
|
|
129
|
+
*/
|
|
130
|
+
connect(): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Disconnect: stop polling
|
|
133
|
+
*/
|
|
134
|
+
disconnect(): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Send a Signal message
|
|
137
|
+
*/
|
|
138
|
+
send(message: OutboundMessage): Promise<DeliveryResult>;
|
|
139
|
+
/**
|
|
140
|
+
* Send a typing indicator
|
|
141
|
+
*/
|
|
142
|
+
sendTyping(recipient: string): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* React to a message with an emoji
|
|
145
|
+
*/
|
|
146
|
+
react(recipient: string, targetAuthor: string, timestamp: number, emoji: string): Promise<void>;
|
|
147
|
+
/**
|
|
148
|
+
* List groups the registered number is a member of
|
|
149
|
+
*/
|
|
150
|
+
listGroups(): Promise<SignalGroup[]>;
|
|
151
|
+
/**
|
|
152
|
+
* Start the message polling loop with reconnection support
|
|
153
|
+
*/
|
|
154
|
+
private startPolling;
|
|
155
|
+
/**
|
|
156
|
+
* Stop polling
|
|
157
|
+
*/
|
|
158
|
+
private stopPolling;
|
|
159
|
+
/**
|
|
160
|
+
* Handle a received Signal message
|
|
161
|
+
*/
|
|
162
|
+
private handleIncoming;
|
|
163
|
+
/**
|
|
164
|
+
* Convert Signal attachments to MessageAttachment format
|
|
165
|
+
*/
|
|
166
|
+
private convertAttachments;
|
|
167
|
+
/**
|
|
168
|
+
* Determine content type from a Signal data message
|
|
169
|
+
*/
|
|
170
|
+
private determineContentType;
|
|
171
|
+
/**
|
|
172
|
+
* Map MIME type to ContentType
|
|
173
|
+
*/
|
|
174
|
+
private mimeToContentType;
|
|
175
|
+
/**
|
|
176
|
+
* Check if an ID looks like a Signal group ID (base64)
|
|
177
|
+
*/
|
|
178
|
+
private isGroupId;
|
|
179
|
+
/**
|
|
180
|
+
* Pre-load groups into the cache
|
|
181
|
+
*/
|
|
182
|
+
private loadGroups;
|
|
183
|
+
}
|
|
184
|
+
export default SignalChannel;
|