botinabox 2.4.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +190 -190
- package/bin/botinabox.mjs +2 -2
- package/dist/channels/slack/index.d.ts +1 -1
- package/dist/{chat-pipeline-BWrtVqEP.d.ts → chat-pipeline-DuNX5WoL.d.ts} +3 -0
- package/dist/cli.js +0 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.js +64 -27
- package/package.json +100 -99
- package/dist/channels/discord/adapter.d.ts +0 -32
- package/dist/channels/discord/adapter.js +0 -70
- package/dist/channels/discord/inbound.d.ts +0 -25
- package/dist/channels/discord/inbound.js +0 -24
- package/dist/channels/discord/models.d.ts +0 -8
- package/dist/channels/discord/models.js +0 -5
- package/dist/channels/discord/outbound.d.ts +0 -14
- package/dist/channels/discord/outbound.js +0 -38
- package/dist/channels/slack/adapter.d.ts +0 -33
- package/dist/channels/slack/adapter.js +0 -74
- package/dist/channels/slack/inbound.d.ts +0 -59
- package/dist/channels/slack/inbound.js +0 -96
- package/dist/channels/slack/models.d.ts +0 -9
- package/dist/channels/slack/models.js +0 -5
- package/dist/channels/slack/outbound.d.ts +0 -12
- package/dist/channels/slack/outbound.js +0 -18
- package/dist/channels/slack/transcribe.d.ts +0 -41
- package/dist/channels/slack/transcribe.js +0 -106
- package/dist/channels/webhook/adapter.d.ts +0 -23
- package/dist/channels/webhook/adapter.js +0 -86
- package/dist/channels/webhook/hmac.d.ts +0 -13
- package/dist/channels/webhook/hmac.js +0 -26
- package/dist/channels/webhook/models.d.ts +0 -9
- package/dist/channels/webhook/models.js +0 -5
- package/dist/channels/webhook/server.d.ts +0 -20
- package/dist/channels/webhook/server.js +0 -91
- package/dist/chat-pipeline-C-XlLGNl.d.ts +0 -648
- package/dist/chat-pipeline-CR1KF6eX.d.ts +0 -652
- package/dist/chat-pipeline-DisuC8SB.d.ts +0 -643
- package/dist/chunk-2LGXQPEA.js +0 -41
- package/dist/chunk-3X3YKI4T.js +0 -357
- package/dist/chunk-D47AIFOD.js +0 -351
- package/dist/chunk-DSNJKNEW.js +0 -328
- package/dist/chunk-GS2JFL6I.js +0 -144
- package/dist/chunk-J6S6QMUY.js +0 -144
- package/dist/chunk-QLA6YOFN.js +0 -22
- package/dist/chunk-UACT2WXX.js +0 -381
- package/dist/cli/templates/config.yml.d.ts +0 -7
- package/dist/cli/templates/config.yml.js +0 -61
- package/dist/cli/templates/env.d.ts +0 -1
- package/dist/cli/templates/env.js +0 -30
- package/dist/cli/templates/index.ts.d.ts +0 -2
- package/dist/cli/templates/index.ts.js +0 -30
- package/dist/cli/templates/package.json.d.ts +0 -5
- package/dist/cli/templates/package.json.js +0 -28
- package/dist/connector-DDahQw-2.d.ts +0 -63
- package/dist/connectors/google/calendar-connector.d.ts +0 -40
- package/dist/connectors/google/calendar-connector.js +0 -243
- package/dist/connectors/google/gmail-connector.d.ts +0 -42
- package/dist/connectors/google/gmail-connector.js +0 -345
- package/dist/connectors/google/oauth.d.ts +0 -48
- package/dist/connectors/google/oauth.js +0 -112
- package/dist/connectors/google/types.d.ts +0 -78
- package/dist/connectors/google/types.js +0 -2
- package/dist/core/chat/auto-discovery.d.ts +0 -16
- package/dist/core/chat/auto-discovery.js +0 -54
- package/dist/core/chat/channel-registry.d.ts +0 -45
- package/dist/core/chat/channel-registry.js +0 -96
- package/dist/core/chat/chat-pipeline.d.ts +0 -113
- package/dist/core/chat/chat-pipeline.js +0 -395
- package/dist/core/chat/chat-responder.d.ts +0 -90
- package/dist/core/chat/chat-responder.js +0 -185
- package/dist/core/chat/formatter.d.ts +0 -11
- package/dist/core/chat/formatter.js +0 -60
- package/dist/core/chat/index.d.ts +0 -24
- package/dist/core/chat/index.js +0 -18
- package/dist/core/chat/message-interpreter.d.ts +0 -91
- package/dist/core/chat/message-interpreter.js +0 -166
- package/dist/core/chat/message-store.d.ts +0 -66
- package/dist/core/chat/message-store.js +0 -131
- package/dist/core/chat/notification-queue.d.ts +0 -34
- package/dist/core/chat/notification-queue.js +0 -111
- package/dist/core/chat/pipeline.d.ts +0 -38
- package/dist/core/chat/pipeline.js +0 -89
- package/dist/core/chat/policies.d.ts +0 -16
- package/dist/core/chat/policies.js +0 -25
- package/dist/core/chat/routing.d.ts +0 -17
- package/dist/core/chat/routing.js +0 -36
- package/dist/core/chat/session-key.d.ts +0 -30
- package/dist/core/chat/session-key.js +0 -65
- package/dist/core/chat/session-manager.d.ts +0 -17
- package/dist/core/chat/session-manager.js +0 -23
- package/dist/core/chat/text-chunker.d.ts +0 -9
- package/dist/core/chat/text-chunker.js +0 -48
- package/dist/core/chat/triage-router.d.ts +0 -75
- package/dist/core/chat/triage-router.js +0 -142
- package/dist/core/chat/types.d.ts +0 -5
- package/dist/core/chat/types.js +0 -5
- package/dist/core/config/defaults.d.ts +0 -2
- package/dist/core/config/defaults.js +0 -38
- package/dist/core/config/index.d.ts +0 -6
- package/dist/core/config/index.js +0 -4
- package/dist/core/config/interpolate.d.ts +0 -5
- package/dist/core/config/interpolate.js +0 -27
- package/dist/core/config/loader.d.ts +0 -24
- package/dist/core/config/loader.js +0 -59
- package/dist/core/config/schema.d.ts +0 -5
- package/dist/core/config/schema.js +0 -119
- package/dist/core/data/core-entity-contexts.d.ts +0 -14
- package/dist/core/data/core-entity-contexts.js +0 -197
- package/dist/core/data/core-migrations.d.ts +0 -5
- package/dist/core/data/core-migrations.js +0 -45
- package/dist/core/data/core-schema.d.ts +0 -6
- package/dist/core/data/core-schema.js +0 -454
- package/dist/core/data/data-store.d.ts +0 -67
- package/dist/core/data/data-store.js +0 -218
- package/dist/core/data/domain-entity-contexts.d.ts +0 -29
- package/dist/core/data/domain-entity-contexts.js +0 -321
- package/dist/core/data/domain-schema.d.ts +0 -36
- package/dist/core/data/domain-schema.js +0 -323
- package/dist/core/data/index.d.ts +0 -7
- package/dist/core/data/index.js +0 -7
- package/dist/core/data/types.d.ts +0 -111
- package/dist/core/data/types.js +0 -1
- package/dist/core/hooks/hook-bus.d.ts +0 -18
- package/dist/core/hooks/hook-bus.js +0 -120
- package/dist/core/hooks/index.d.ts +0 -2
- package/dist/core/hooks/index.js +0 -1
- package/dist/core/hooks/types.d.ts +0 -19
- package/dist/core/hooks/types.js +0 -1
- package/dist/core/index.d.ts +0 -4
- package/dist/core/index.js +0 -4
- package/dist/core/llm/auto-discovery.d.ts +0 -11
- package/dist/core/llm/auto-discovery.js +0 -49
- package/dist/core/llm/cost-tracker.d.ts +0 -6
- package/dist/core/llm/cost-tracker.js +0 -38
- package/dist/core/llm/index.d.ts +0 -4
- package/dist/core/llm/index.js +0 -3
- package/dist/core/llm/model-router.d.ts +0 -25
- package/dist/core/llm/model-router.js +0 -49
- package/dist/core/llm/provider-registry.d.ts +0 -9
- package/dist/core/llm/provider-registry.js +0 -25
- package/dist/core/llm/types.d.ts +0 -2
- package/dist/core/llm/types.js +0 -2
- package/dist/core/orchestrator/adapters/api-adapter.d.ts +0 -34
- package/dist/core/orchestrator/adapters/api-adapter.js +0 -88
- package/dist/core/orchestrator/adapters/cli-adapter.d.ts +0 -22
- package/dist/core/orchestrator/adapters/cli-adapter.js +0 -69
- package/dist/core/orchestrator/adapters/deterministic-adapter.d.ts +0 -35
- package/dist/core/orchestrator/adapters/deterministic-adapter.js +0 -75
- package/dist/core/orchestrator/adapters/env-whitelist.d.ts +0 -4
- package/dist/core/orchestrator/adapters/env-whitelist.js +0 -27
- package/dist/core/orchestrator/adapters/output-extractor.d.ts +0 -11
- package/dist/core/orchestrator/adapters/output-extractor.js +0 -59
- package/dist/core/orchestrator/adapters/process-manager.d.ts +0 -15
- package/dist/core/orchestrator/adapters/process-manager.js +0 -26
- package/dist/core/orchestrator/adapters/tool-loop.d.ts +0 -22
- package/dist/core/orchestrator/adapters/tool-loop.js +0 -66
- package/dist/core/orchestrator/agent-registry.d.ts +0 -31
- package/dist/core/orchestrator/agent-registry.js +0 -135
- package/dist/core/orchestrator/budget-controller.d.ts +0 -19
- package/dist/core/orchestrator/budget-controller.js +0 -73
- package/dist/core/orchestrator/chain-guard.d.ts +0 -14
- package/dist/core/orchestrator/chain-guard.js +0 -23
- package/dist/core/orchestrator/circuit-breaker.d.ts +0 -65
- package/dist/core/orchestrator/circuit-breaker.js +0 -159
- package/dist/core/orchestrator/claude-stream-parser.d.ts +0 -31
- package/dist/core/orchestrator/claude-stream-parser.js +0 -99
- package/dist/core/orchestrator/config-revisions.d.ts +0 -6
- package/dist/core/orchestrator/config-revisions.js +0 -17
- package/dist/core/orchestrator/dependency-resolver.d.ts +0 -20
- package/dist/core/orchestrator/dependency-resolver.js +0 -78
- package/dist/core/orchestrator/governance-gate.d.ts +0 -110
- package/dist/core/orchestrator/governance-gate.js +0 -170
- package/dist/core/orchestrator/learning-pipeline.d.ts +0 -109
- package/dist/core/orchestrator/learning-pipeline.js +0 -249
- package/dist/core/orchestrator/loop-detector.d.ts +0 -51
- package/dist/core/orchestrator/loop-detector.js +0 -133
- package/dist/core/orchestrator/ndjson-logger.d.ts +0 -6
- package/dist/core/orchestrator/ndjson-logger.js +0 -18
- package/dist/core/orchestrator/permission-relay.d.ts +0 -72
- package/dist/core/orchestrator/permission-relay.js +0 -164
- package/dist/core/orchestrator/run-manager.d.ts +0 -31
- package/dist/core/orchestrator/run-manager.js +0 -178
- package/dist/core/orchestrator/scheduler.d.ts +0 -70
- package/dist/core/orchestrator/scheduler.js +0 -198
- package/dist/core/orchestrator/secret-store.d.ts +0 -57
- package/dist/core/orchestrator/secret-store.js +0 -171
- package/dist/core/orchestrator/session-manager.d.ts +0 -13
- package/dist/core/orchestrator/session-manager.js +0 -66
- package/dist/core/orchestrator/task-queue.d.ts +0 -34
- package/dist/core/orchestrator/task-queue.js +0 -83
- package/dist/core/orchestrator/template-interpolate.d.ts +0 -5
- package/dist/core/orchestrator/template-interpolate.js +0 -18
- package/dist/core/orchestrator/user-registry.d.ts +0 -47
- package/dist/core/orchestrator/user-registry.js +0 -76
- package/dist/core/orchestrator/wakeup-queue.d.ts +0 -9
- package/dist/core/orchestrator/wakeup-queue.js +0 -45
- package/dist/core/orchestrator/workflow-engine.d.ts +0 -47
- package/dist/core/orchestrator/workflow-engine.js +0 -204
- package/dist/core/security/audit.d.ts +0 -20
- package/dist/core/security/audit.js +0 -33
- package/dist/core/security/column-validator.d.ts +0 -20
- package/dist/core/security/column-validator.js +0 -37
- package/dist/core/security/index.d.ts +0 -5
- package/dist/core/security/index.js +0 -5
- package/dist/core/security/process-env.d.ts +0 -13
- package/dist/core/security/process-env.js +0 -49
- package/dist/core/security/sanitizer.d.ts +0 -11
- package/dist/core/security/sanitizer.js +0 -39
- package/dist/core/security/types.d.ts +0 -11
- package/dist/core/security/types.js +0 -1
- package/dist/core/update/auto-update.d.ts +0 -21
- package/dist/core/update/auto-update.js +0 -102
- package/dist/core/update/backup-manager.d.ts +0 -7
- package/dist/core/update/backup-manager.js +0 -24
- package/dist/core/update/index.d.ts +0 -8
- package/dist/core/update/index.js +0 -6
- package/dist/core/update/migration-hooks.d.ts +0 -11
- package/dist/core/update/migration-hooks.js +0 -10
- package/dist/core/update/types.d.ts +0 -11
- package/dist/core/update/types.js +0 -1
- package/dist/core/update/update-checker.d.ts +0 -11
- package/dist/core/update/update-checker.js +0 -63
- package/dist/core/update/update-manager.d.ts +0 -25
- package/dist/core/update/update-manager.js +0 -101
- package/dist/core/update/version-utils.d.ts +0 -6
- package/dist/core/update/version-utils.js +0 -34
- package/dist/gmail-connector-2FVYTQJH.js +0 -6
- package/dist/gmail-connector-MNUBRNFM.js +0 -6
- package/dist/gmail-connector-PS2VLGNE.js +0 -6
- package/dist/gmail-connector-ULSMN6X2.js +0 -6
- package/dist/gmail-connector-URRFX6A3.js +0 -6
- package/dist/inbound-AFBUPSPG.js +0 -10
- package/dist/inbound-AFOHYNUY.js +0 -6
- package/dist/inbound-CGIXRXGC.js +0 -8
- package/dist/inbound-MCOLRH6U.js +0 -10
- package/dist/inbound-SNEMBLGA.js +0 -6
- package/dist/inbound-ZJHAYVMF.js +0 -10
- package/dist/provider-qqJYv9nv.d.ts +0 -75
- package/dist/providers/anthropic/models.d.ts +0 -2
- package/dist/providers/anthropic/models.js +0 -29
- package/dist/providers/anthropic/provider.d.ts +0 -13
- package/dist/providers/anthropic/provider.js +0 -119
- package/dist/providers/anthropic/tool-converter.d.ts +0 -10
- package/dist/providers/anthropic/tool-converter.js +0 -7
- package/dist/providers/ollama/provider.d.ts +0 -17
- package/dist/providers/ollama/provider.js +0 -185
- package/dist/providers/openai/models.d.ts +0 -2
- package/dist/providers/openai/models.js +0 -29
- package/dist/providers/openai/provider.d.ts +0 -13
- package/dist/providers/openai/provider.js +0 -163
- package/dist/providers/openai/tool-converter.d.ts +0 -10
- package/dist/providers/openai/tool-converter.js +0 -10
- package/dist/shared/constants.d.ts +0 -50
- package/dist/shared/constants.js +0 -64
- package/dist/shared/index.d.ts +0 -14
- package/dist/shared/index.js +0 -14
- package/dist/shared/types/agent.d.ts +0 -36
- package/dist/shared/types/agent.js +0 -2
- package/dist/shared/types/channel.d.ts +0 -70
- package/dist/shared/types/channel.js +0 -2
- package/dist/shared/types/config.d.ts +0 -111
- package/dist/shared/types/config.js +0 -2
- package/dist/shared/types/connector.d.ts +0 -77
- package/dist/shared/types/connector.js +0 -2
- package/dist/shared/types/execution.d.ts +0 -29
- package/dist/shared/types/execution.js +0 -2
- package/dist/shared/types/provider.d.ts +0 -73
- package/dist/shared/types/provider.js +0 -2
- package/dist/shared/types/task.d.ts +0 -47
- package/dist/shared/types/task.js +0 -2
- package/dist/shared/types/workflow.d.ts +0 -39
- package/dist/shared/types/workflow.js +0 -2
- package/dist/shared/utils.d.ts +0 -6
- package/dist/shared/utils.js +0 -13
- package/dist/update-check.d.ts +0 -5
- package/dist/update-check.js +0 -56
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SlackAdapter — ChannelAdapter implementation for Slack.
|
|
3
|
-
* Story 4.5
|
|
4
|
-
*/
|
|
5
|
-
import type { ChannelAdapter, ChannelCapabilities, ChannelMeta, ChannelConfig, InboundMessage, OutboundPayload, SendResult, HealthStatus } from "../../shared/index.js";
|
|
6
|
-
/** Minimal Bolt-compatible client interface for mockability. */
|
|
7
|
-
export interface BoltClient {
|
|
8
|
-
postMessage(channel: string, text: string, threadTs?: string): Promise<{
|
|
9
|
-
ok: boolean;
|
|
10
|
-
ts?: string;
|
|
11
|
-
}>;
|
|
12
|
-
}
|
|
13
|
-
export declare class SlackAdapter implements ChannelAdapter {
|
|
14
|
-
readonly id = "slack";
|
|
15
|
-
readonly meta: ChannelMeta;
|
|
16
|
-
readonly capabilities: ChannelCapabilities;
|
|
17
|
-
onMessage?: (message: InboundMessage) => Promise<void>;
|
|
18
|
-
private connected;
|
|
19
|
-
private config;
|
|
20
|
-
private client;
|
|
21
|
-
constructor(client?: BoltClient);
|
|
22
|
-
connect(config: ChannelConfig): Promise<void>;
|
|
23
|
-
disconnect(): Promise<void>;
|
|
24
|
-
healthCheck(): Promise<HealthStatus>;
|
|
25
|
-
send(target: {
|
|
26
|
-
peerId: string;
|
|
27
|
-
threadId?: string;
|
|
28
|
-
}, payload: OutboundPayload): Promise<SendResult>;
|
|
29
|
-
/** Simulate receiving an inbound message (for testing/webhooks). */
|
|
30
|
-
receive(event: Record<string, unknown>): Promise<void>;
|
|
31
|
-
}
|
|
32
|
-
/** Factory function — default export for auto-discovery. */
|
|
33
|
-
export default function createSlackAdapter(client?: BoltClient): SlackAdapter;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SlackAdapter — ChannelAdapter implementation for Slack.
|
|
3
|
-
* Story 4.5
|
|
4
|
-
*/
|
|
5
|
-
import { formatForSlack } from "./outbound.js";
|
|
6
|
-
export class SlackAdapter {
|
|
7
|
-
id = "slack";
|
|
8
|
-
meta = {
|
|
9
|
-
displayName: "Slack",
|
|
10
|
-
icon: "https://slack.com/favicon.ico",
|
|
11
|
-
homepage: "https://slack.com",
|
|
12
|
-
};
|
|
13
|
-
capabilities = {
|
|
14
|
-
chatTypes: ["direct", "group", "channel"],
|
|
15
|
-
threads: true,
|
|
16
|
-
reactions: true,
|
|
17
|
-
editing: true,
|
|
18
|
-
media: true,
|
|
19
|
-
polls: false,
|
|
20
|
-
maxTextLength: 40_000,
|
|
21
|
-
formattingMode: "mrkdwn",
|
|
22
|
-
};
|
|
23
|
-
onMessage;
|
|
24
|
-
connected = false;
|
|
25
|
-
config = null;
|
|
26
|
-
client;
|
|
27
|
-
constructor(client) {
|
|
28
|
-
this.client = client ?? null;
|
|
29
|
-
}
|
|
30
|
-
async connect(config) {
|
|
31
|
-
this.config = config;
|
|
32
|
-
this.connected = true;
|
|
33
|
-
}
|
|
34
|
-
async disconnect() {
|
|
35
|
-
this.connected = false;
|
|
36
|
-
this.config = null;
|
|
37
|
-
}
|
|
38
|
-
async healthCheck() {
|
|
39
|
-
return { ok: this.connected };
|
|
40
|
-
}
|
|
41
|
-
async send(target, payload) {
|
|
42
|
-
if (!this.connected) {
|
|
43
|
-
return { success: false, error: "Not connected" };
|
|
44
|
-
}
|
|
45
|
-
const text = formatForSlack(payload.text);
|
|
46
|
-
if (this.client) {
|
|
47
|
-
try {
|
|
48
|
-
const result = await this.client.postMessage(target.peerId, text, target.threadId);
|
|
49
|
-
return { success: result.ok, messageId: result.ts };
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
return { success: false, error: String(err) };
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
// No-op when no client provided
|
|
56
|
-
return { success: true };
|
|
57
|
-
}
|
|
58
|
-
/** Simulate receiving an inbound message (for testing/webhooks). */
|
|
59
|
-
async receive(event) {
|
|
60
|
-
if (this.onMessage) {
|
|
61
|
-
const { parseSlackEvent } = await import("./inbound.js");
|
|
62
|
-
const { enrichVoiceMessage } = await import("./inbound.js");
|
|
63
|
-
let msg = parseSlackEvent(event);
|
|
64
|
-
if (msg.body.includes("[Voice message") && this.config?.botToken) {
|
|
65
|
-
msg = await enrichVoiceMessage(msg, this.config.botToken);
|
|
66
|
-
}
|
|
67
|
-
await this.onMessage(msg);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/** Factory function — default export for auto-discovery. */
|
|
72
|
-
export default function createSlackAdapter(client) {
|
|
73
|
-
return new SlackAdapter(client);
|
|
74
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack inbound message parsing.
|
|
3
|
-
* Story 4.5
|
|
4
|
-
*/
|
|
5
|
-
import type { InboundMessage } from "../../shared/index.js";
|
|
6
|
-
export interface SlackFile {
|
|
7
|
-
id?: string;
|
|
8
|
-
filetype?: string;
|
|
9
|
-
subtype?: string;
|
|
10
|
-
url_private?: string;
|
|
11
|
-
preview?: string;
|
|
12
|
-
transcription?: {
|
|
13
|
-
status?: string;
|
|
14
|
-
preview?: {
|
|
15
|
-
content?: string;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
[key: string]: unknown;
|
|
19
|
-
}
|
|
20
|
-
export interface SlackEvent {
|
|
21
|
-
type: string;
|
|
22
|
-
subtype?: string;
|
|
23
|
-
client_msg_id?: string;
|
|
24
|
-
ts?: string;
|
|
25
|
-
event_ts?: string;
|
|
26
|
-
channel?: string;
|
|
27
|
-
user?: string;
|
|
28
|
-
text?: string;
|
|
29
|
-
thread_ts?: string;
|
|
30
|
-
files?: SlackFile[];
|
|
31
|
-
[key: string]: unknown;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Extract the text content from a voice message file.
|
|
35
|
-
* Prefers the transcription preview; falls back to the file preview text.
|
|
36
|
-
* Returns null if the file is not a voice message or has no transcript.
|
|
37
|
-
*/
|
|
38
|
-
export declare function extractVoiceTranscript(file: SlackFile): string | null;
|
|
39
|
-
/**
|
|
40
|
-
* Parse a Slack event into an InboundMessage.
|
|
41
|
-
*
|
|
42
|
-
* Handles standard text messages and voice messages (file_share subtype
|
|
43
|
-
* with audio files). Voice message transcripts are extracted and prefixed
|
|
44
|
-
* with `[Voice message]`.
|
|
45
|
-
*/
|
|
46
|
-
export declare function parseSlackEvent(event: SlackEvent): InboundMessage;
|
|
47
|
-
/**
|
|
48
|
-
* Enrich a voice message with local transcription when Slack's built-in
|
|
49
|
-
* transcription is unavailable.
|
|
50
|
-
*
|
|
51
|
-
* Downloads the audio file from Slack using the bot token, converts to WAV,
|
|
52
|
-
* and transcribes locally via whisper-node. Returns the original message
|
|
53
|
-
* unchanged if transcription fails or is not needed.
|
|
54
|
-
*
|
|
55
|
-
* @param msg - The parsed inbound message (from parseSlackEvent)
|
|
56
|
-
* @param botToken - Slack bot token for authenticated file download
|
|
57
|
-
* @returns The message with body replaced by transcript, or original on failure
|
|
58
|
-
*/
|
|
59
|
-
export declare function enrichVoiceMessage(msg: InboundMessage, botToken: string): Promise<InboundMessage>;
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack inbound message parsing.
|
|
3
|
-
* Story 4.5
|
|
4
|
-
*/
|
|
5
|
-
import { transcribeAudio, downloadAudio } from "./transcribe.js";
|
|
6
|
-
const AUDIO_TYPES = new Set(["aac", "mp4", "m4a", "ogg", "webm", "mp3", "wav"]);
|
|
7
|
-
/**
|
|
8
|
-
* Extract the text content from a voice message file.
|
|
9
|
-
* Prefers the transcription preview; falls back to the file preview text.
|
|
10
|
-
* Returns null if the file is not a voice message or has no transcript.
|
|
11
|
-
*/
|
|
12
|
-
export function extractVoiceTranscript(file) {
|
|
13
|
-
const isAudio = file.subtype === "slack_audio" || AUDIO_TYPES.has(file.filetype ?? "");
|
|
14
|
-
if (!isAudio)
|
|
15
|
-
return null;
|
|
16
|
-
const transcript = file.transcription?.preview?.content ??
|
|
17
|
-
(typeof file.preview === "string" ? file.preview : null);
|
|
18
|
-
return transcript ?? null;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Parse a Slack event into an InboundMessage.
|
|
22
|
-
*
|
|
23
|
-
* Handles standard text messages and voice messages (file_share subtype
|
|
24
|
-
* with audio files). Voice message transcripts are extracted and prefixed
|
|
25
|
-
* with `[Voice message]`.
|
|
26
|
-
*/
|
|
27
|
-
export function parseSlackEvent(event) {
|
|
28
|
-
const id = event.client_msg_id ?? event.ts ?? event.event_ts ?? `slack-${Date.now()}`;
|
|
29
|
-
const channel = event.channel ?? "unknown";
|
|
30
|
-
const from = event.user ?? "unknown";
|
|
31
|
-
const threadId = event.thread_ts !== undefined ? event.thread_ts : undefined;
|
|
32
|
-
const receivedAt = event.ts
|
|
33
|
-
? new Date(parseFloat(event.ts) * 1000).toISOString()
|
|
34
|
-
: new Date().toISOString();
|
|
35
|
-
let body = event.text ?? "";
|
|
36
|
-
// Voice messages: extract transcript from audio file attachments
|
|
37
|
-
if (event.subtype === "file_share" && event.files?.length) {
|
|
38
|
-
for (const file of event.files) {
|
|
39
|
-
const transcript = extractVoiceTranscript(file);
|
|
40
|
-
if (transcript) {
|
|
41
|
-
body = body ? `${body}\n\n[Voice message] ${transcript}` : `[Voice message] ${transcript}`;
|
|
42
|
-
break; // Only one voice message per event
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// If voice message had no Slack transcript, mark for local transcription
|
|
47
|
-
if (event.subtype === "file_share" && event.files?.length && !body) {
|
|
48
|
-
const hasAudio = event.files.some((f) => f.subtype === "slack_audio" || AUDIO_TYPES.has(f.filetype ?? ""));
|
|
49
|
-
if (hasAudio) {
|
|
50
|
-
body = "[Voice message — no transcript available]";
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
id,
|
|
55
|
-
channel,
|
|
56
|
-
from,
|
|
57
|
-
body,
|
|
58
|
-
threadId,
|
|
59
|
-
receivedAt,
|
|
60
|
-
raw: event,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Enrich a voice message with local transcription when Slack's built-in
|
|
65
|
-
* transcription is unavailable.
|
|
66
|
-
*
|
|
67
|
-
* Downloads the audio file from Slack using the bot token, converts to WAV,
|
|
68
|
-
* and transcribes locally via whisper-node. Returns the original message
|
|
69
|
-
* unchanged if transcription fails or is not needed.
|
|
70
|
-
*
|
|
71
|
-
* @param msg - The parsed inbound message (from parseSlackEvent)
|
|
72
|
-
* @param botToken - Slack bot token for authenticated file download
|
|
73
|
-
* @returns The message with body replaced by transcript, or original on failure
|
|
74
|
-
*/
|
|
75
|
-
export async function enrichVoiceMessage(msg, botToken) {
|
|
76
|
-
if (!msg.body.includes("[Voice message — no transcript available]"))
|
|
77
|
-
return msg;
|
|
78
|
-
const raw = msg.raw;
|
|
79
|
-
const files = raw?.files;
|
|
80
|
-
if (!files?.length)
|
|
81
|
-
return msg;
|
|
82
|
-
const audioFile = files.find((f) => f.subtype === "slack_audio" || AUDIO_TYPES.has(f.filetype ?? ""));
|
|
83
|
-
if (!audioFile?.url_private)
|
|
84
|
-
return msg;
|
|
85
|
-
const buffer = await downloadAudio(audioFile.url_private, botToken);
|
|
86
|
-
if (!buffer)
|
|
87
|
-
return msg;
|
|
88
|
-
const filename = audioFile.name ?? `voice.${audioFile.filetype ?? "aac"}`;
|
|
89
|
-
const transcript = await transcribeAudio(buffer, filename);
|
|
90
|
-
if (!transcript)
|
|
91
|
-
return msg;
|
|
92
|
-
return {
|
|
93
|
-
...msg,
|
|
94
|
-
body: `[Voice message] ${transcript}`,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack outbound formatting.
|
|
3
|
-
* Story 4.5
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Convert standard markdown to Slack's mrkdwn format.
|
|
7
|
-
* - **bold** → *bold*
|
|
8
|
-
* - _italic_ preserved
|
|
9
|
-
* - `code` preserved
|
|
10
|
-
* - ```code block``` preserved
|
|
11
|
-
*/
|
|
12
|
-
export declare function formatForSlack(text: string): string;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slack outbound formatting.
|
|
3
|
-
* Story 4.5
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Convert standard markdown to Slack's mrkdwn format.
|
|
7
|
-
* - **bold** → *bold*
|
|
8
|
-
* - _italic_ preserved
|
|
9
|
-
* - `code` preserved
|
|
10
|
-
* - ```code block``` preserved
|
|
11
|
-
*/
|
|
12
|
-
export function formatForSlack(text) {
|
|
13
|
-
// **bold** → *bold*
|
|
14
|
-
let result = text.replace(/\*\*(.+?)\*\*/gs, "*$1*");
|
|
15
|
-
// __bold__ → *bold*
|
|
16
|
-
result = result.replace(/__(.+?)__/gs, "*$1*");
|
|
17
|
-
return result;
|
|
18
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Local voice transcription via whisper-node (whisper.cpp bindings).
|
|
3
|
-
*
|
|
4
|
-
* whisper-node is an optional dependency — if not installed, transcription
|
|
5
|
-
* degrades gracefully (returns null). Requires ffmpeg on the system PATH
|
|
6
|
-
* for audio format conversion.
|
|
7
|
-
*
|
|
8
|
-
* Setup:
|
|
9
|
-
* npm install whisper-node
|
|
10
|
-
* npx whisper-node download # download a model (e.g. base.en)
|
|
11
|
-
* brew install ffmpeg # or equivalent for your platform
|
|
12
|
-
*/
|
|
13
|
-
export interface TranscribeOptions {
|
|
14
|
-
/** Whisper model name (default: "base.en"). Run `npx whisper-node download` to get models. */
|
|
15
|
-
modelName?: string;
|
|
16
|
-
/** Language code (default: "auto"). Use "en" for English-only models. */
|
|
17
|
-
language?: string;
|
|
18
|
-
}
|
|
19
|
-
export interface TranscribeResult {
|
|
20
|
-
/** The full transcribed text */
|
|
21
|
-
text: string;
|
|
22
|
-
/** Individual segments with timestamps */
|
|
23
|
-
segments: Array<{
|
|
24
|
-
start: string;
|
|
25
|
-
end: string;
|
|
26
|
-
speech: string;
|
|
27
|
-
}>;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Transcribe an audio buffer using whisper-node.
|
|
31
|
-
*
|
|
32
|
-
* @param audioBuffer - Raw audio data (any format ffmpeg can decode)
|
|
33
|
-
* @param filename - Original filename (used for temp file extension)
|
|
34
|
-
* @param opts - Transcription options
|
|
35
|
-
* @returns Transcribed text, or null if transcription fails or whisper-node is not installed
|
|
36
|
-
*/
|
|
37
|
-
export declare function transcribeAudio(audioBuffer: Buffer, filename: string, opts?: TranscribeOptions): Promise<string | null>;
|
|
38
|
-
/**
|
|
39
|
-
* Download an audio file from a URL with bearer token authentication.
|
|
40
|
-
*/
|
|
41
|
-
export declare function downloadAudio(url: string, token: string): Promise<Buffer | null>;
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Local voice transcription via whisper-node (whisper.cpp bindings).
|
|
3
|
-
*
|
|
4
|
-
* whisper-node is an optional dependency — if not installed, transcription
|
|
5
|
-
* degrades gracefully (returns null). Requires ffmpeg on the system PATH
|
|
6
|
-
* for audio format conversion.
|
|
7
|
-
*
|
|
8
|
-
* Setup:
|
|
9
|
-
* npm install whisper-node
|
|
10
|
-
* npx whisper-node download # download a model (e.g. base.en)
|
|
11
|
-
* brew install ffmpeg # or equivalent for your platform
|
|
12
|
-
*/
|
|
13
|
-
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { writeFileSync, unlinkSync, mkdirSync } from "node:fs";
|
|
15
|
-
import { join } from "node:path";
|
|
16
|
-
import { randomUUID } from "node:crypto";
|
|
17
|
-
import os from "node:os";
|
|
18
|
-
import { createRequire } from "node:module";
|
|
19
|
-
const TEMP_DIR = join(os.tmpdir(), "botinabox-audio");
|
|
20
|
-
/**
|
|
21
|
-
* Transcribe an audio buffer using whisper-node.
|
|
22
|
-
*
|
|
23
|
-
* @param audioBuffer - Raw audio data (any format ffmpeg can decode)
|
|
24
|
-
* @param filename - Original filename (used for temp file extension)
|
|
25
|
-
* @param opts - Transcription options
|
|
26
|
-
* @returns Transcribed text, or null if transcription fails or whisper-node is not installed
|
|
27
|
-
*/
|
|
28
|
-
export async function transcribeAudio(audioBuffer, filename, opts) {
|
|
29
|
-
// Lazy-load whisper-node (optional CJS dependency)
|
|
30
|
-
let whisper;
|
|
31
|
-
try {
|
|
32
|
-
const require = createRequire(import.meta.url);
|
|
33
|
-
const mod = require("whisper-node");
|
|
34
|
-
whisper = mod.whisper ?? mod.default ?? mod;
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
console.warn("[botinabox] whisper-node not installed — voice transcription unavailable. Run: npm install whisper-node && npx whisper-node download");
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
// Check ffmpeg availability
|
|
41
|
-
try {
|
|
42
|
-
execFileSync("ffmpeg", ["-version"], { stdio: "ignore" });
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
console.warn("[botinabox] ffmpeg not found — required for audio conversion. Install: brew install ffmpeg");
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
const id = randomUUID().slice(0, 8);
|
|
49
|
-
const ext = filename.split(".").pop() ?? "aac";
|
|
50
|
-
mkdirSync(TEMP_DIR, { recursive: true });
|
|
51
|
-
const inputPath = join(TEMP_DIR, `${id}.${ext}`);
|
|
52
|
-
const wavPath = join(TEMP_DIR, `${id}.wav`);
|
|
53
|
-
try {
|
|
54
|
-
// Write audio to temp file
|
|
55
|
-
writeFileSync(inputPath, audioBuffer);
|
|
56
|
-
// Convert to WAV 16kHz mono PCM (required by whisper.cpp)
|
|
57
|
-
execFileSync("ffmpeg", ["-y", "-i", inputPath, "-ar", "16000", "-ac", "1", "-c:a", "pcm_s16le", wavPath], {
|
|
58
|
-
stdio: "ignore",
|
|
59
|
-
timeout: 30_000,
|
|
60
|
-
});
|
|
61
|
-
// Transcribe
|
|
62
|
-
const segments = await whisper(wavPath, {
|
|
63
|
-
modelName: opts?.modelName ?? "base.en",
|
|
64
|
-
whisperOptions: {
|
|
65
|
-
language: opts?.language ?? "auto",
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
if (!segments || segments.length === 0)
|
|
69
|
-
return null;
|
|
70
|
-
return segments.map((s) => s.speech).join(" ").trim();
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
console.error("[botinabox] Transcription failed:", err);
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
// Clean up temp files
|
|
78
|
-
try {
|
|
79
|
-
unlinkSync(inputPath);
|
|
80
|
-
}
|
|
81
|
-
catch { /* ignore */ }
|
|
82
|
-
try {
|
|
83
|
-
unlinkSync(wavPath);
|
|
84
|
-
}
|
|
85
|
-
catch { /* ignore */ }
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Download an audio file from a URL with bearer token authentication.
|
|
90
|
-
*/
|
|
91
|
-
export async function downloadAudio(url, token) {
|
|
92
|
-
try {
|
|
93
|
-
const resp = await fetch(url, {
|
|
94
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
95
|
-
});
|
|
96
|
-
if (!resp.ok) {
|
|
97
|
-
console.error(`[botinabox] Audio download failed: ${resp.status} ${resp.statusText}`);
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
return Buffer.from(await resp.arrayBuffer());
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
console.error("[botinabox] Audio download error:", err);
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WebhookAdapter — ChannelAdapter implementation for webhook-based channels.
|
|
3
|
-
* Story 4.7
|
|
4
|
-
*/
|
|
5
|
-
import type { ChannelAdapter, ChannelCapabilities, ChannelMeta, ChannelConfig, InboundMessage, OutboundPayload, SendResult, HealthStatus } from "../../shared/index.js";
|
|
6
|
-
export declare class WebhookAdapter implements ChannelAdapter {
|
|
7
|
-
readonly id = "webhook";
|
|
8
|
-
readonly meta: ChannelMeta;
|
|
9
|
-
readonly capabilities: ChannelCapabilities;
|
|
10
|
-
onMessage?: (message: InboundMessage) => Promise<void>;
|
|
11
|
-
private connected;
|
|
12
|
-
private config;
|
|
13
|
-
private webhookServer;
|
|
14
|
-
connect(config: ChannelConfig): Promise<void>;
|
|
15
|
-
disconnect(): Promise<void>;
|
|
16
|
-
healthCheck(): Promise<HealthStatus>;
|
|
17
|
-
send(target: {
|
|
18
|
-
peerId: string;
|
|
19
|
-
threadId?: string;
|
|
20
|
-
}, payload: OutboundPayload): Promise<SendResult>;
|
|
21
|
-
}
|
|
22
|
-
/** Factory function — default export for auto-discovery. */
|
|
23
|
-
export default function createWebhookAdapter(): WebhookAdapter;
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WebhookAdapter — ChannelAdapter implementation for webhook-based channels.
|
|
3
|
-
* Story 4.7
|
|
4
|
-
*/
|
|
5
|
-
import { WebhookServer } from "./server.js";
|
|
6
|
-
export class WebhookAdapter {
|
|
7
|
-
id = "webhook";
|
|
8
|
-
meta = {
|
|
9
|
-
displayName: "Webhook",
|
|
10
|
-
homepage: "https://example.com",
|
|
11
|
-
};
|
|
12
|
-
capabilities = {
|
|
13
|
-
chatTypes: ["direct"],
|
|
14
|
-
threads: false,
|
|
15
|
-
reactions: false,
|
|
16
|
-
editing: false,
|
|
17
|
-
media: false,
|
|
18
|
-
polls: false,
|
|
19
|
-
maxTextLength: 65535,
|
|
20
|
-
formattingMode: "plain",
|
|
21
|
-
};
|
|
22
|
-
onMessage;
|
|
23
|
-
connected = false;
|
|
24
|
-
config = null;
|
|
25
|
-
webhookServer = null;
|
|
26
|
-
async connect(config) {
|
|
27
|
-
this.config = config;
|
|
28
|
-
this.connected = true;
|
|
29
|
-
// Start webhook HTTP server if port is specified
|
|
30
|
-
if (this.config.port) {
|
|
31
|
-
this.webhookServer = new WebhookServer({
|
|
32
|
-
port: this.config.port,
|
|
33
|
-
secret: this.config.secret,
|
|
34
|
-
onMessage: async (msg) => {
|
|
35
|
-
if (this.onMessage)
|
|
36
|
-
await this.onMessage(msg);
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
await this.webhookServer.start();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async disconnect() {
|
|
43
|
-
if (this.webhookServer) {
|
|
44
|
-
await this.webhookServer.stop();
|
|
45
|
-
this.webhookServer = null;
|
|
46
|
-
}
|
|
47
|
-
this.connected = false;
|
|
48
|
-
this.config = null;
|
|
49
|
-
}
|
|
50
|
-
async healthCheck() {
|
|
51
|
-
return { ok: this.connected };
|
|
52
|
-
}
|
|
53
|
-
async send(target, payload) {
|
|
54
|
-
if (!this.connected) {
|
|
55
|
-
return { success: false, error: "Not connected" };
|
|
56
|
-
}
|
|
57
|
-
const callbackUrl = this.config?.callbackUrl;
|
|
58
|
-
if (!callbackUrl) {
|
|
59
|
-
// No callback URL configured — accept silently (fire-and-forget style)
|
|
60
|
-
return { success: true };
|
|
61
|
-
}
|
|
62
|
-
try {
|
|
63
|
-
const body = JSON.stringify({
|
|
64
|
-
to: target.peerId,
|
|
65
|
-
threadId: target.threadId,
|
|
66
|
-
text: payload.text,
|
|
67
|
-
});
|
|
68
|
-
const response = await fetch(callbackUrl, {
|
|
69
|
-
method: "POST",
|
|
70
|
-
headers: { "Content-Type": "application/json" },
|
|
71
|
-
body,
|
|
72
|
-
});
|
|
73
|
-
if (response.ok) {
|
|
74
|
-
return { success: true };
|
|
75
|
-
}
|
|
76
|
-
return { success: false, error: `HTTP ${response.status}` };
|
|
77
|
-
}
|
|
78
|
-
catch (err) {
|
|
79
|
-
return { success: false, error: String(err) };
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/** Factory function — default export for auto-discovery. */
|
|
84
|
-
export default function createWebhookAdapter() {
|
|
85
|
-
return new WebhookAdapter();
|
|
86
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HMAC signature verification for webhook payloads.
|
|
3
|
-
* Story 4.7
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Verify that the HMAC-SHA256 signature of body matches the provided signature.
|
|
7
|
-
* Uses timing-safe comparison to prevent timing attacks.
|
|
8
|
-
*
|
|
9
|
-
* @param body - The raw request body string
|
|
10
|
-
* @param secret - The shared HMAC secret
|
|
11
|
-
* @param signature - The signature to verify (hex string, possibly prefixed with "sha256=")
|
|
12
|
-
*/
|
|
13
|
-
export declare function verifyHmac(body: string, secret: string, signature: string): boolean;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HMAC signature verification for webhook payloads.
|
|
3
|
-
* Story 4.7
|
|
4
|
-
*/
|
|
5
|
-
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
6
|
-
/**
|
|
7
|
-
* Verify that the HMAC-SHA256 signature of body matches the provided signature.
|
|
8
|
-
* Uses timing-safe comparison to prevent timing attacks.
|
|
9
|
-
*
|
|
10
|
-
* @param body - The raw request body string
|
|
11
|
-
* @param secret - The shared HMAC secret
|
|
12
|
-
* @param signature - The signature to verify (hex string, possibly prefixed with "sha256=")
|
|
13
|
-
*/
|
|
14
|
-
export function verifyHmac(body, secret, signature) {
|
|
15
|
-
const expected = createHmac("sha256", secret).update(body, "utf8").digest("hex");
|
|
16
|
-
// Strip optional "sha256=" prefix
|
|
17
|
-
const provided = signature.startsWith("sha256=") ? signature.slice(7) : signature;
|
|
18
|
-
if (expected.length !== provided.length)
|
|
19
|
-
return false;
|
|
20
|
-
try {
|
|
21
|
-
return timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(provided, "hex"));
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal HTTP server for webhook inbound messages.
|
|
3
|
-
* Story 4.7
|
|
4
|
-
*/
|
|
5
|
-
import type { InboundMessage } from "../../shared/index.js";
|
|
6
|
-
export interface WebhookServerOpts {
|
|
7
|
-
port?: number;
|
|
8
|
-
secret?: string;
|
|
9
|
-
onMessage: (msg: InboundMessage) => Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
export declare class WebhookServer {
|
|
12
|
-
private server;
|
|
13
|
-
private readonly port;
|
|
14
|
-
private readonly secret;
|
|
15
|
-
private readonly onMessage;
|
|
16
|
-
constructor(opts: WebhookServerOpts);
|
|
17
|
-
start(): Promise<void>;
|
|
18
|
-
stop(): Promise<void>;
|
|
19
|
-
private handleRequest;
|
|
20
|
-
}
|