botinabox 2.9.0 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +2 -1
  2. package/dist/channels/discord/adapter.d.ts +32 -0
  3. package/dist/channels/discord/inbound.d.ts +25 -0
  4. package/dist/channels/discord/index.d.ts +8 -84
  5. package/dist/channels/discord/models.d.ts +8 -0
  6. package/dist/channels/discord/outbound.d.ts +14 -0
  7. package/dist/channels/slack/adapter.d.ts +33 -0
  8. package/dist/channels/slack/bolt-adapter.d.ts +31 -0
  9. package/dist/channels/slack/enrichers/enrich.d.ts +12 -0
  10. package/dist/channels/slack/enrichers/image-enricher.d.ts +10 -0
  11. package/dist/channels/slack/enrichers/index.d.ts +4 -0
  12. package/dist/channels/slack/enrichers/pdf-enricher.d.ts +8 -0
  13. package/dist/channels/slack/enrichers/types.d.ts +33 -0
  14. package/dist/channels/slack/inbound.d.ts +59 -0
  15. package/dist/channels/slack/index.d.ts +13 -252
  16. package/dist/channels/slack/index.js +6 -2
  17. package/dist/channels/slack/media-type.d.ts +14 -0
  18. package/dist/channels/slack/models.d.ts +9 -0
  19. package/dist/channels/slack/outbound.d.ts +12 -0
  20. package/dist/channels/slack/transcribe.d.ts +41 -0
  21. package/dist/channels/webhook/adapter.d.ts +23 -0
  22. package/dist/channels/webhook/hmac.d.ts +13 -0
  23. package/dist/channels/webhook/index.d.ts +7 -70
  24. package/dist/channels/webhook/models.d.ts +9 -0
  25. package/dist/channels/webhook/server.d.ts +20 -0
  26. package/dist/cli/templates/config.yml.d.ts +7 -0
  27. package/dist/cli/templates/env.d.ts +1 -0
  28. package/dist/cli/templates/index.ts.d.ts +2 -0
  29. package/dist/cli/templates/package.json.d.ts +5 -0
  30. package/dist/cli.d.ts +1 -3
  31. package/dist/connectors/google/calendar-connector.d.ts +40 -0
  32. package/dist/connectors/google/drive-connector.d.ts +43 -0
  33. package/dist/connectors/google/drive-read.d.ts +81 -0
  34. package/dist/connectors/google/gmail-connector.d.ts +42 -0
  35. package/dist/connectors/google/index.d.ts +10 -369
  36. package/dist/connectors/google/oauth.d.ts +48 -0
  37. package/dist/connectors/google/types.d.ts +110 -0
  38. package/dist/core/chat/auto-discovery.d.ts +16 -0
  39. package/dist/core/chat/channel-registry.d.ts +45 -0
  40. package/dist/core/chat/chat-pipeline-v2.d.ts +138 -0
  41. package/dist/core/chat/chat-pipeline.d.ts +116 -0
  42. package/dist/core/chat/chat-responder.d.ts +94 -0
  43. package/dist/core/chat/formatter.d.ts +11 -0
  44. package/dist/core/chat/index.d.ts +26 -0
  45. package/dist/core/chat/message-interpreter.d.ts +91 -0
  46. package/dist/core/chat/message-store.d.ts +71 -0
  47. package/dist/core/chat/notification-queue.d.ts +34 -0
  48. package/dist/core/chat/pipeline.d.ts +38 -0
  49. package/dist/core/chat/policies.d.ts +16 -0
  50. package/dist/core/chat/routing.d.ts +17 -0
  51. package/dist/core/chat/session-key.d.ts +30 -0
  52. package/dist/core/chat/session-manager.d.ts +17 -0
  53. package/dist/core/chat/text-chunker.d.ts +9 -0
  54. package/dist/core/chat/triage-router.d.ts +75 -0
  55. package/dist/core/chat/types.d.ts +5 -0
  56. package/dist/core/config/defaults.d.ts +2 -0
  57. package/dist/core/config/index.d.ts +6 -0
  58. package/dist/core/config/interpolate.d.ts +5 -0
  59. package/dist/core/config/loader.d.ts +24 -0
  60. package/dist/core/config/schema.d.ts +5 -0
  61. package/dist/core/data/context-builder.d.ts +27 -0
  62. package/dist/core/data/core-entity-contexts.d.ts +14 -0
  63. package/dist/core/data/core-migrations.d.ts +5 -0
  64. package/dist/core/data/core-schema.d.ts +6 -0
  65. package/dist/core/data/data-store.d.ts +67 -0
  66. package/dist/core/data/domain-entity-contexts.d.ts +35 -0
  67. package/dist/core/data/domain-schema.d.ts +36 -0
  68. package/dist/core/data/index.d.ts +8 -0
  69. package/dist/core/data/types.d.ts +111 -0
  70. package/dist/core/hooks/hook-bus.d.ts +24 -0
  71. package/dist/core/hooks/index.d.ts +2 -0
  72. package/dist/core/hooks/types.d.ts +19 -0
  73. package/dist/core/index.d.ts +4 -0
  74. package/dist/core/llm/auto-discovery.d.ts +11 -0
  75. package/dist/core/llm/cost-tracker.d.ts +6 -0
  76. package/dist/core/llm/default-llm-call.d.ts +35 -0
  77. package/dist/core/llm/index.d.ts +6 -0
  78. package/dist/core/llm/model-router.d.ts +25 -0
  79. package/dist/core/llm/provider-registry.d.ts +9 -0
  80. package/dist/core/llm/types.d.ts +2 -0
  81. package/dist/core/orchestrator/adapters/api-adapter.d.ts +34 -0
  82. package/dist/core/orchestrator/adapters/cli-adapter.d.ts +62 -0
  83. package/dist/core/orchestrator/adapters/deterministic-adapter.d.ts +35 -0
  84. package/dist/core/orchestrator/adapters/env-whitelist.d.ts +4 -0
  85. package/dist/core/orchestrator/adapters/output-extractor.d.ts +11 -0
  86. package/dist/core/orchestrator/adapters/process-manager.d.ts +15 -0
  87. package/dist/core/orchestrator/adapters/tool-loop.d.ts +22 -0
  88. package/dist/core/orchestrator/agent-registry.d.ts +31 -0
  89. package/dist/core/orchestrator/budget-controller.d.ts +19 -0
  90. package/dist/core/orchestrator/chain-guard.d.ts +14 -0
  91. package/dist/core/orchestrator/circuit-breaker.d.ts +65 -0
  92. package/dist/core/orchestrator/claude-stream-parser.d.ts +31 -0
  93. package/dist/core/orchestrator/config-revisions.d.ts +6 -0
  94. package/dist/core/orchestrator/dependency-resolver.d.ts +20 -0
  95. package/dist/core/orchestrator/execution-engine.d.ts +99 -0
  96. package/dist/core/orchestrator/governance-gate.d.ts +110 -0
  97. package/dist/core/orchestrator/learning-pipeline.d.ts +112 -0
  98. package/dist/core/orchestrator/loop-detector.d.ts +51 -0
  99. package/dist/core/orchestrator/ndjson-logger.d.ts +6 -0
  100. package/dist/core/orchestrator/permission-relay.d.ts +72 -0
  101. package/dist/core/orchestrator/run-manager.d.ts +31 -0
  102. package/dist/core/orchestrator/scheduler.d.ts +74 -0
  103. package/dist/core/orchestrator/secret-store.d.ts +57 -0
  104. package/dist/core/orchestrator/session-manager.d.ts +13 -0
  105. package/dist/core/orchestrator/task-queue.d.ts +34 -0
  106. package/dist/core/orchestrator/template-interpolate.d.ts +5 -0
  107. package/dist/core/orchestrator/tools/file-ops.d.ts +12 -0
  108. package/dist/core/orchestrator/tools/index.d.ts +47 -0
  109. package/dist/core/orchestrator/tools/management.d.ts +12 -0
  110. package/dist/core/orchestrator/tools/messaging.d.ts +21 -0
  111. package/dist/core/orchestrator/tools/read-file.d.ts +5 -0
  112. package/dist/core/orchestrator/tools/resolve-agent.d.ts +9 -0
  113. package/dist/core/orchestrator/tools/roster.d.ts +16 -0
  114. package/dist/core/orchestrator/tools/send-file.d.ts +5 -0
  115. package/dist/core/orchestrator/tools/status.d.ts +20 -0
  116. package/dist/core/orchestrator/tools/task-ops.d.ts +13 -0
  117. package/dist/core/orchestrator/user-registry.d.ts +47 -0
  118. package/dist/core/orchestrator/wakeup-queue.d.ts +9 -0
  119. package/dist/core/orchestrator/workflow-engine.d.ts +47 -0
  120. package/dist/core/security/audit.d.ts +20 -0
  121. package/dist/core/security/column-validator.d.ts +20 -0
  122. package/dist/core/security/index.d.ts +5 -0
  123. package/dist/core/security/process-env.d.ts +13 -0
  124. package/dist/core/security/sanitizer.d.ts +11 -0
  125. package/dist/core/security/types.d.ts +11 -0
  126. package/dist/core/update/auto-update.d.ts +21 -0
  127. package/dist/core/update/backup-manager.d.ts +7 -0
  128. package/dist/core/update/index.d.ts +8 -0
  129. package/dist/core/update/migration-hooks.d.ts +11 -0
  130. package/dist/core/update/types.d.ts +11 -0
  131. package/dist/core/update/update-checker.d.ts +11 -0
  132. package/dist/core/update/update-manager.d.ts +25 -0
  133. package/dist/core/update/version-utils.d.ts +6 -0
  134. package/dist/index.d.ts +38 -2366
  135. package/dist/index.js +112 -5
  136. package/dist/providers/anthropic/index.d.ts +5 -20
  137. package/dist/providers/anthropic/models.d.ts +2 -0
  138. package/dist/providers/anthropic/provider.d.ts +13 -0
  139. package/dist/providers/anthropic/tool-converter.d.ts +10 -0
  140. package/dist/providers/ollama/index.d.ts +4 -22
  141. package/dist/providers/ollama/provider.d.ts +17 -0
  142. package/dist/providers/openai/index.d.ts +5 -20
  143. package/dist/providers/openai/models.d.ts +2 -0
  144. package/dist/providers/openai/provider.d.ts +13 -0
  145. package/dist/providers/openai/tool-converter.d.ts +10 -0
  146. package/dist/shared/constants.d.ts +50 -0
  147. package/dist/shared/index.d.ts +14 -0
  148. package/dist/shared/types/agent.d.ts +36 -0
  149. package/dist/shared/types/channel.d.ts +78 -0
  150. package/dist/shared/types/config.d.ts +160 -0
  151. package/dist/shared/types/connector.d.ts +77 -0
  152. package/dist/shared/types/execution.d.ts +29 -0
  153. package/dist/shared/types/provider.d.ts +87 -0
  154. package/dist/shared/types/task.d.ts +47 -0
  155. package/dist/shared/types/workflow.d.ts +39 -0
  156. package/dist/shared/utils.d.ts +6 -0
  157. package/dist/update-check.d.ts +5 -0
  158. package/package.json +2 -2
package/README.md CHANGED
@@ -13,7 +13,8 @@ A modular TypeScript framework for building multi-agent bots with LLM orchestrat
13
13
  - **Message interpretation** -- Async structured extraction from messages into tasks, memories, files, and user context. Pluggable extractors for custom data types. Programmatic task creation (no LLM dependency).
14
14
  - **Triage routing** -- Content-aware message routing with keyword/regex matching, priority rules, and LLM fallback. Ownership chain logging for every routing decision.
15
15
  - **Multi-agent orchestration** -- Define agents with different models, roles, and execution adapters. Task queue with priority scheduling, retry policies, and followup chains.
16
- - **Loop detection and circuit breakers** -- Pattern-based loop detection (self-loops, ping-pong, blocked re-entry) plus circuit breakers with automatic human escalation.
16
+ - **Loop detection and circuit breakers** -- Pattern-based loop detection (self-loops, ping-pong, blocked re-entry) plus circuit breakers with automatic human escalation. Scheduler connector syncs are circuit-broken per key — persistent connector failures trip the breaker instead of retrying endlessly.
17
+ - **Safe tool merging** -- `mergeTools(nativeTools, localSkills)` deduplicates tool arrays with last-wins semantics. Prevents Anthropic API 400 errors from duplicate tool names when combining built-in and custom tools.
17
18
  - **Learning pipeline** -- Structured feedback capture with auto-promotion: 3+ similar records become a playbook, 3+ agents become a reusable skill.
18
19
  - **Governance gates** -- Independent QA, quality, and drift gates that validate agent output and report to the human operator.
19
20
  - **Permission relay** -- Remote approval via messaging platforms (Slack, Discord, Telegram). Dual approval: local + remote, first wins.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * DiscordAdapter — ChannelAdapter implementation for Discord.
3
+ * Story 4.6
4
+ */
5
+ import type { ChannelAdapter, ChannelCapabilities, ChannelMeta, ChannelConfig, InboundMessage, OutboundPayload, SendResult, HealthStatus } from "../../shared/index.js";
6
+ /** Minimal Discord client interface for mockability. */
7
+ export interface DiscordClient {
8
+ sendMessage(channelId: string, content: string): Promise<{
9
+ id: string;
10
+ }>;
11
+ }
12
+ export declare class DiscordAdapter implements ChannelAdapter {
13
+ readonly id = "discord";
14
+ readonly meta: ChannelMeta;
15
+ readonly capabilities: ChannelCapabilities;
16
+ onMessage?: (message: InboundMessage) => Promise<void>;
17
+ private connected;
18
+ private config;
19
+ private client;
20
+ constructor(client?: DiscordClient);
21
+ connect(config: ChannelConfig): Promise<void>;
22
+ disconnect(): Promise<void>;
23
+ healthCheck(): Promise<HealthStatus>;
24
+ send(target: {
25
+ peerId: string;
26
+ threadId?: string;
27
+ }, payload: OutboundPayload): Promise<SendResult>;
28
+ /** Simulate receiving an inbound message (for testing/webhooks). */
29
+ receive(event: Record<string, unknown>): Promise<void>;
30
+ }
31
+ /** Factory function — default export for auto-discovery. */
32
+ export default function createDiscordAdapter(client?: DiscordClient): DiscordAdapter;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Discord inbound message parsing.
3
+ * Story 4.6
4
+ */
5
+ import type { InboundMessage } from "../../shared/index.js";
6
+ export interface DiscordEvent {
7
+ id?: string;
8
+ channel_id?: string;
9
+ guild_id?: string;
10
+ author?: {
11
+ id?: string;
12
+ username?: string;
13
+ };
14
+ content?: string;
15
+ message_reference?: {
16
+ message_id?: string;
17
+ channel_id?: string;
18
+ };
19
+ timestamp?: string;
20
+ [key: string]: unknown;
21
+ }
22
+ /**
23
+ * Parse a Discord message event into an InboundMessage.
24
+ */
25
+ export declare function parseDiscordEvent(event: DiscordEvent): InboundMessage;
@@ -1,87 +1,11 @@
1
- import { C as ChannelAdapter, d as ChannelMeta, b as ChannelCapabilities, I as InboundMessage, c as ChannelConfig, H as HealthStatus, O as OutboundPayload, S as SendResult } from '../../channel-CVm1AWUF.js';
2
- import '../../provider-BHkqkSdq.js';
3
-
4
1
  /**
5
- * DiscordAdapterChannelAdapter implementation for Discord.
2
+ * @botinabox/channel-discordDiscord channel adapter.
6
3
  * Story 4.6
7
4
  */
8
-
9
- /** Minimal Discord client interface for mockability. */
10
- interface DiscordClient {
11
- sendMessage(channelId: string, content: string): Promise<{
12
- id: string;
13
- }>;
14
- }
15
- declare class DiscordAdapter implements ChannelAdapter {
16
- readonly id = "discord";
17
- readonly meta: ChannelMeta;
18
- readonly capabilities: ChannelCapabilities;
19
- onMessage?: (message: InboundMessage) => Promise<void>;
20
- private connected;
21
- private config;
22
- private client;
23
- constructor(client?: DiscordClient);
24
- connect(config: ChannelConfig): Promise<void>;
25
- disconnect(): Promise<void>;
26
- healthCheck(): Promise<HealthStatus>;
27
- send(target: {
28
- peerId: string;
29
- threadId?: string;
30
- }, payload: OutboundPayload): Promise<SendResult>;
31
- /** Simulate receiving an inbound message (for testing/webhooks). */
32
- receive(event: Record<string, unknown>): Promise<void>;
33
- }
34
- /** Factory function — default export for auto-discovery. */
35
- declare function createDiscordAdapter(client?: DiscordClient): DiscordAdapter;
36
-
37
- /**
38
- * Discord inbound message parsing.
39
- * Story 4.6
40
- */
41
-
42
- interface DiscordEvent {
43
- id?: string;
44
- channel_id?: string;
45
- guild_id?: string;
46
- author?: {
47
- id?: string;
48
- username?: string;
49
- };
50
- content?: string;
51
- message_reference?: {
52
- message_id?: string;
53
- channel_id?: string;
54
- };
55
- timestamp?: string;
56
- [key: string]: unknown;
57
- }
58
- /**
59
- * Parse a Discord message event into an InboundMessage.
60
- */
61
- declare function parseDiscordEvent(event: DiscordEvent): InboundMessage;
62
-
63
- /**
64
- * Discord outbound formatting.
65
- * Discord uses native markdown — just enforce the 2000-char limit.
66
- * Story 4.6
67
- */
68
- /**
69
- * Split text into Discord-compatible chunks (2000 char max each).
70
- */
71
- declare function chunkForDiscord(text: string): string[];
72
- /**
73
- * Discord uses native markdown — no conversion needed.
74
- * Returns the text unchanged (Discord renders it natively).
75
- */
76
- declare function formatForDiscord(text: string): string;
77
-
78
- /**
79
- * Discord channel configuration types.
80
- * Story 4.6
81
- */
82
- interface DiscordConfig {
83
- token: string;
84
- guildId?: string;
85
- }
86
-
87
- export { DiscordAdapter, type DiscordClient, type DiscordConfig, type DiscordEvent, chunkForDiscord, createDiscordAdapter as default, formatForDiscord, parseDiscordEvent };
5
+ export { DiscordAdapter } from "./adapter.js";
6
+ export type { DiscordClient } from "./adapter.js";
7
+ export { parseDiscordEvent } from "./inbound.js";
8
+ export type { DiscordEvent } from "./inbound.js";
9
+ export { formatForDiscord, chunkForDiscord } from "./outbound.js";
10
+ export type { DiscordConfig } from "./models.js";
11
+ export { default } from "./adapter.js";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Discord channel configuration types.
3
+ * Story 4.6
4
+ */
5
+ export interface DiscordConfig {
6
+ token: string;
7
+ guildId?: string;
8
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Discord outbound formatting.
3
+ * Discord uses native markdown — just enforce the 2000-char limit.
4
+ * Story 4.6
5
+ */
6
+ /**
7
+ * Split text into Discord-compatible chunks (2000 char max each).
8
+ */
9
+ export declare function chunkForDiscord(text: string): string[];
10
+ /**
11
+ * Discord uses native markdown — no conversion needed.
12
+ * Returns the text unchanged (Discord renders it natively).
13
+ */
14
+ export declare function formatForDiscord(text: string): string;
@@ -0,0 +1,33 @@
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;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * SlackBoltAdapter — real Bolt Socket Mode integration for botinabox.
3
+ *
4
+ * Handles:
5
+ * - Bolt app lifecycle (start, stop)
6
+ * - Inbound message parsing + self-filtering
7
+ * - response.ready → Slack message delivery
8
+ * - file.deliver → Slack file upload
9
+ *
10
+ * Apps just instantiate and start:
11
+ * const slack = new SlackBoltAdapter({ botToken, appToken, hooks, pipeline });
12
+ * await slack.start();
13
+ */
14
+ import type { HookBus } from '../../core/hooks/hook-bus.js';
15
+ import type { ChatPipeline } from '../../core/chat/chat-pipeline.js';
16
+ import type { AttachmentEnricherMap } from './enrichers/types.js';
17
+ export interface SlackBoltAdapterConfig {
18
+ botToken: string;
19
+ appToken: string;
20
+ hooks: HookBus;
21
+ pipeline: ChatPipeline;
22
+ /** Optional per-type attachment enrichers. */
23
+ attachmentEnrichers?: AttachmentEnricherMap;
24
+ }
25
+ export declare class SlackBoltAdapter {
26
+ private app;
27
+ private config;
28
+ constructor(config: SlackBoltAdapterConfig);
29
+ start(): Promise<void>;
30
+ stop(): Promise<void>;
31
+ }
@@ -0,0 +1,12 @@
1
+ import type { InboundMessage } from "../../../shared/types/channel.js";
2
+ import type { AttachmentEnricherMap, EnrichmentContext } from "./types.js";
3
+ /**
4
+ * Run enrichers over each attachment on an InboundMessage. Text blocks get
5
+ * appended to `body`; image/document blocks get stored on `attachmentBlocks`
6
+ * so ChatPipeline can assemble a multimodal user message.
7
+ *
8
+ * Enrichers that throw or return empty arrays fall back to a plain
9
+ * `[Attached: <filename>]` breadcrumb — the LLM still sees the attachment
10
+ * was there, just without content.
11
+ */
12
+ export declare function enrichAttachments(msg: InboundMessage, ctx: EnrichmentContext, enrichers: AttachmentEnricherMap): Promise<InboundMessage>;
@@ -0,0 +1,10 @@
1
+ import type { AttachmentEnricher } from "./types.js";
2
+ /**
3
+ * Slack image enricher. Downloads the image via the Slack bot token and
4
+ * returns a single `image` ContentBlock containing the base64 data. No
5
+ * intermediate vision API call — the downstream Anthropic provider sees
6
+ * the raw image and processes it natively.
7
+ *
8
+ * Consumers wire this as `attachmentEnrichers.image = createSlackImageEnricher()`.
9
+ */
10
+ export declare function createSlackImageEnricher(): AttachmentEnricher;
@@ -0,0 +1,4 @@
1
+ export type { AttachmentEnricher, AttachmentEnricherMap, EnrichmentContext, EnrichedMessage, } from "./types.js";
2
+ export { enrichAttachments } from "./enrich.js";
3
+ export { createSlackImageEnricher } from "./image-enricher.js";
4
+ export { createSlackPdfEnricher } from "./pdf-enricher.js";
@@ -0,0 +1,8 @@
1
+ import type { AttachmentEnricher } from "./types.js";
2
+ /**
3
+ * Slack PDF enricher. Downloads the PDF via the Slack bot token and returns
4
+ * a single `document` ContentBlock containing the base64 data. No intermediate
5
+ * document-extraction API call — the downstream Anthropic provider ingests
6
+ * the PDF natively.
7
+ */
8
+ export declare function createSlackPdfEnricher(): AttachmentEnricher;
@@ -0,0 +1,33 @@
1
+ import type { Attachment, AttachmentMediaType, InboundMessage } from "../../../shared/types/channel.js";
2
+ import type { ContentBlock } from "../../../shared/types/provider.js";
3
+ /**
4
+ * Transport-specific context passed to every enricher. Extensible — add a new
5
+ * optional sub-context when wiring a new source (gmail, drive, dropbox, etc.)
6
+ * and enrichers that need it can type-guard.
7
+ */
8
+ export interface EnrichmentContext {
9
+ slack?: {
10
+ botToken: string;
11
+ };
12
+ drive?: {
13
+ client: unknown;
14
+ };
15
+ gmail?: {
16
+ client: unknown;
17
+ };
18
+ }
19
+ /**
20
+ * An AttachmentEnricher downloads an attachment and returns Claude content
21
+ * blocks representing it. Text blocks become part of the message body; image
22
+ * and document blocks flow through to the Anthropic provider unchanged.
23
+ *
24
+ * Enrichers throw on failure. The framework catches and falls back to a
25
+ * plain `[Attached: <filename>]` breadcrumb in the message body.
26
+ */
27
+ export type AttachmentEnricher = (attachment: Attachment, ctx: EnrichmentContext) => Promise<ContentBlock[]>;
28
+ export type AttachmentEnricherMap = Partial<Record<AttachmentMediaType, AttachmentEnricher>>;
29
+ /** Internal: the result of running enrichAttachments on a message. */
30
+ export interface EnrichedMessage extends InboundMessage {
31
+ body: string;
32
+ }
33
+ export type { InboundMessage };
@@ -0,0 +1,59 @@
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,255 +1,16 @@
1
- import { C as ChannelAdapter, d as ChannelMeta, b as ChannelCapabilities, I as InboundMessage, c as ChannelConfig, H as HealthStatus, O as OutboundPayload, S as SendResult, A as Attachment, a as AttachmentMediaType } from '../../channel-CVm1AWUF.js';
2
- import { H as HookBus, c as ChatPipeline } from '../../chat-pipeline-aBSj7a4E.js';
3
- import { c as ContentBlock } from '../../provider-BHkqkSdq.js';
4
- import 'better-sqlite3';
5
-
6
1
  /**
7
- * SlackAdapterChannelAdapter implementation for Slack.
2
+ * @botinabox/channel-slackSlack channel adapter.
8
3
  * Story 4.5
9
4
  */
10
-
11
- /** Minimal Bolt-compatible client interface for mockability. */
12
- interface BoltClient {
13
- postMessage(channel: string, text: string, threadTs?: string): Promise<{
14
- ok: boolean;
15
- ts?: string;
16
- }>;
17
- }
18
- declare class SlackAdapter implements ChannelAdapter {
19
- readonly id = "slack";
20
- readonly meta: ChannelMeta;
21
- readonly capabilities: ChannelCapabilities;
22
- onMessage?: (message: InboundMessage) => Promise<void>;
23
- private connected;
24
- private config;
25
- private client;
26
- constructor(client?: BoltClient);
27
- connect(config: ChannelConfig): Promise<void>;
28
- disconnect(): Promise<void>;
29
- healthCheck(): Promise<HealthStatus>;
30
- send(target: {
31
- peerId: string;
32
- threadId?: string;
33
- }, payload: OutboundPayload): Promise<SendResult>;
34
- /** Simulate receiving an inbound message (for testing/webhooks). */
35
- receive(event: Record<string, unknown>): Promise<void>;
36
- }
37
- /** Factory function — default export for auto-discovery. */
38
- declare function createSlackAdapter(client?: BoltClient): SlackAdapter;
39
-
40
- /**
41
- * Slack inbound message parsing.
42
- * Story 4.5
43
- */
44
-
45
- interface SlackFile {
46
- id?: string;
47
- filetype?: string;
48
- subtype?: string;
49
- url_private?: string;
50
- preview?: string;
51
- transcription?: {
52
- status?: string;
53
- preview?: {
54
- content?: string;
55
- };
56
- };
57
- [key: string]: unknown;
58
- }
59
- interface SlackEvent {
60
- type: string;
61
- subtype?: string;
62
- client_msg_id?: string;
63
- ts?: string;
64
- event_ts?: string;
65
- channel?: string;
66
- user?: string;
67
- text?: string;
68
- thread_ts?: string;
69
- files?: SlackFile[];
70
- [key: string]: unknown;
71
- }
72
- /**
73
- * Extract the text content from a voice message file.
74
- * Prefers the transcription preview; falls back to the file preview text.
75
- * Returns null if the file is not a voice message or has no transcript.
76
- */
77
- declare function extractVoiceTranscript(file: SlackFile): string | null;
78
- /**
79
- * Parse a Slack event into an InboundMessage.
80
- *
81
- * Handles standard text messages and voice messages (file_share subtype
82
- * with audio files). Voice message transcripts are extracted and prefixed
83
- * with `[Voice message]`.
84
- */
85
- declare function parseSlackEvent(event: SlackEvent): InboundMessage;
86
- /**
87
- * Enrich a voice message with local transcription when Slack's built-in
88
- * transcription is unavailable.
89
- *
90
- * Downloads the audio file from Slack using the bot token, converts to WAV,
91
- * and transcribes locally via whisper-node. Returns the original message
92
- * unchanged if transcription fails or is not needed.
93
- *
94
- * @param msg - The parsed inbound message (from parseSlackEvent)
95
- * @param botToken - Slack bot token for authenticated file download
96
- * @returns The message with body replaced by transcript, or original on failure
97
- */
98
- declare function enrichVoiceMessage(msg: InboundMessage, botToken: string): Promise<InboundMessage>;
99
-
100
- /**
101
- * Local voice transcription via whisper-node (whisper.cpp bindings).
102
- *
103
- * whisper-node is an optional dependency — if not installed, transcription
104
- * degrades gracefully (returns null). Requires ffmpeg on the system PATH
105
- * for audio format conversion.
106
- *
107
- * Setup:
108
- * npm install whisper-node
109
- * npx whisper-node download # download a model (e.g. base.en)
110
- * brew install ffmpeg # or equivalent for your platform
111
- */
112
- interface TranscribeOptions {
113
- /** Whisper model name (default: "base.en"). Run `npx whisper-node download` to get models. */
114
- modelName?: string;
115
- /** Language code (default: "auto"). Use "en" for English-only models. */
116
- language?: string;
117
- }
118
- interface TranscribeResult {
119
- /** The full transcribed text */
120
- text: string;
121
- /** Individual segments with timestamps */
122
- segments: Array<{
123
- start: string;
124
- end: string;
125
- speech: string;
126
- }>;
127
- }
128
- /**
129
- * Transcribe an audio buffer using whisper-node.
130
- *
131
- * @param audioBuffer - Raw audio data (any format ffmpeg can decode)
132
- * @param filename - Original filename (used for temp file extension)
133
- * @param opts - Transcription options
134
- * @returns Transcribed text, or null if transcription fails or whisper-node is not installed
135
- */
136
- declare function transcribeAudio(audioBuffer: Buffer, filename: string, opts?: TranscribeOptions): Promise<string | null>;
137
- /**
138
- * Download an audio file from a URL with bearer token authentication.
139
- */
140
- declare function downloadAudio(url: string, token: string): Promise<Buffer | null>;
141
-
142
- /**
143
- * Slack outbound formatting.
144
- * Story 4.5
145
- */
146
- /**
147
- * Convert standard markdown to Slack's mrkdwn format.
148
- * - **bold** → *bold*
149
- * - _italic_ preserved
150
- * - `code` preserved
151
- * - ```code block``` preserved
152
- */
153
- declare function formatForSlack(text: string): string;
154
-
155
- /**
156
- * Slack channel configuration types.
157
- * Story 4.5
158
- */
159
- interface SlackConfig {
160
- botToken: string;
161
- appToken?: string;
162
- signingSecret?: string;
163
- }
164
-
165
- /**
166
- * Transport-specific context passed to every enricher. Extensible — add a new
167
- * optional sub-context when wiring a new source (gmail, drive, dropbox, etc.)
168
- * and enrichers that need it can type-guard.
169
- */
170
- interface EnrichmentContext {
171
- slack?: {
172
- botToken: string;
173
- };
174
- drive?: {
175
- client: unknown;
176
- };
177
- gmail?: {
178
- client: unknown;
179
- };
180
- }
181
- /**
182
- * An AttachmentEnricher downloads an attachment and returns Claude content
183
- * blocks representing it. Text blocks become part of the message body; image
184
- * and document blocks flow through to the Anthropic provider unchanged.
185
- *
186
- * Enrichers throw on failure. The framework catches and falls back to a
187
- * plain `[Attached: <filename>]` breadcrumb in the message body.
188
- */
189
- type AttachmentEnricher = (attachment: Attachment, ctx: EnrichmentContext) => Promise<ContentBlock[]>;
190
- type AttachmentEnricherMap = Partial<Record<AttachmentMediaType, AttachmentEnricher>>;
191
- /** Internal: the result of running enrichAttachments on a message. */
192
- interface EnrichedMessage extends InboundMessage {
193
- body: string;
194
- }
195
-
196
- /**
197
- * SlackBoltAdapter — real Bolt Socket Mode integration for botinabox.
198
- *
199
- * Handles:
200
- * - Bolt app lifecycle (start, stop)
201
- * - Inbound message parsing + self-filtering
202
- * - response.ready → Slack message delivery
203
- * - file.deliver → Slack file upload
204
- *
205
- * Apps just instantiate and start:
206
- * const slack = new SlackBoltAdapter({ botToken, appToken, hooks, pipeline });
207
- * await slack.start();
208
- */
209
-
210
- interface SlackBoltAdapterConfig {
211
- botToken: string;
212
- appToken: string;
213
- hooks: HookBus;
214
- pipeline: ChatPipeline;
215
- /** Optional per-type attachment enrichers. */
216
- attachmentEnrichers?: AttachmentEnricherMap;
217
- }
218
- declare class SlackBoltAdapter {
219
- private app;
220
- private config;
221
- constructor(config: SlackBoltAdapterConfig);
222
- start(): Promise<void>;
223
- stop(): Promise<void>;
224
- }
225
-
226
- /**
227
- * Run enrichers over each attachment on an InboundMessage. Text blocks get
228
- * appended to `body`; image/document blocks get stored on `attachmentBlocks`
229
- * so ChatPipeline can assemble a multimodal user message.
230
- *
231
- * Enrichers that throw or return empty arrays fall back to a plain
232
- * `[Attached: <filename>]` breadcrumb — the LLM still sees the attachment
233
- * was there, just without content.
234
- */
235
- declare function enrichAttachments(msg: InboundMessage, ctx: EnrichmentContext, enrichers: AttachmentEnricherMap): Promise<InboundMessage>;
236
-
237
- /**
238
- * Slack image enricher. Downloads the image via the Slack bot token and
239
- * returns a single `image` ContentBlock containing the base64 data. No
240
- * intermediate vision API call — the downstream Anthropic provider sees
241
- * the raw image and processes it natively.
242
- *
243
- * Consumers wire this as `attachmentEnrichers.image = createSlackImageEnricher()`.
244
- */
245
- declare function createSlackImageEnricher(): AttachmentEnricher;
246
-
247
- /**
248
- * Slack PDF enricher. Downloads the PDF via the Slack bot token and returns
249
- * a single `document` ContentBlock containing the base64 data. No intermediate
250
- * document-extraction API call — the downstream Anthropic provider ingests
251
- * the PDF natively.
252
- */
253
- declare function createSlackPdfEnricher(): AttachmentEnricher;
254
-
255
- export { type AttachmentEnricher, type AttachmentEnricherMap, type BoltClient, type EnrichedMessage, type EnrichmentContext, SlackAdapter, SlackBoltAdapter, type SlackBoltAdapterConfig, type SlackConfig, type SlackEvent, type SlackFile, type TranscribeOptions, type TranscribeResult, createSlackImageEnricher, createSlackPdfEnricher, createSlackAdapter as default, downloadAudio, enrichAttachments, enrichVoiceMessage, extractVoiceTranscript, formatForSlack, parseSlackEvent, transcribeAudio };
5
+ export { SlackAdapter } from "./adapter.js";
6
+ export type { BoltClient } from "./adapter.js";
7
+ export { parseSlackEvent, extractVoiceTranscript, enrichVoiceMessage } from "./inbound.js";
8
+ export type { SlackEvent, SlackFile } from "./inbound.js";
9
+ export { transcribeAudio, downloadAudio } from "./transcribe.js";
10
+ export type { TranscribeOptions, TranscribeResult } from "./transcribe.js";
11
+ export { formatForSlack } from "./outbound.js";
12
+ export type { SlackConfig } from "./models.js";
13
+ export { SlackBoltAdapter } from "./bolt-adapter.js";
14
+ export type { SlackBoltAdapterConfig } from "./bolt-adapter.js";
15
+ export { default } from "./adapter.js";
16
+ export * from "./enrichers/index.js";