botinabox 0.6.0 → 1.0.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/README.md CHANGED
@@ -4,173 +4,248 @@ A modular TypeScript framework for building multi-agent bots with LLM orchestrat
4
4
 
5
5
  ## Features
6
6
 
7
- - **Multi-agent orchestration** -- Define agents with different models, roles, and execution adapters. Task queue with priority scheduling, retry policies, and followup chains.
8
- - **LLM provider abstraction** -- Swap between Anthropic, OpenAI, and Ollama with a unified interface. Model aliasing, purpose-based routing, and fallback chains.
9
- - **Channel adapters** -- Connect to Slack, Discord, and webhooks. Auto-discovery, session management, and notification queuing.
10
- - **Workflow engine** -- Define multi-step workflows with dependency resolution, parallel execution, and conditional branching.
11
- - **SQLite data layer** -- Schema-driven tables, migrations, entity context rendering, and query builder via [latticesql](https://github.com/automated-industries/lattice). WAL mode for concurrent reads.
12
- - **Event-driven hooks** -- Priority-ordered, filter-based event bus for decoupled inter-layer communication.
13
- - **Budget controls** -- Per-agent and global cost tracking with warning thresholds and hard stops.
14
- - **Scheduling** -- Database-backed cron and one-time schedules that fire hook events.
15
- - **Google connectors** -- Gmail and Calendar integration via OAuth2.
16
- - **Security** -- Input sanitization, field length enforcement, audit logging, and HMAC webhook verification.
17
-
18
- ## Install
7
+ - **Multi-agent orchestration** Define agents with different models, roles, and execution adapters. Task queue with priority scheduling, retry policies, and followup chains.
8
+ - **LLM provider abstraction** Swap between Anthropic, OpenAI, and Ollama with a unified interface. Model aliasing, purpose-based routing, and fallback chains.
9
+ - **Channel adapters** Connect to Slack, Discord, and webhooks. Auto-discovery, session management, and notification queuing.
10
+ - **Workflow engine** Define multi-step workflows with dependency resolution, parallel execution, and conditional branching.
11
+ - **SQLite data layer** Schema-driven tables, migrations, entity context rendering, and query builder. WAL mode for concurrent reads.
12
+ - **Event-driven hooks** Priority-ordered, filter-based event bus for decoupled inter-layer communication.
13
+ - **Budget controls** Per-agent and global cost tracking with warning thresholds and hard stops.
14
+ - **Protected primitives** Users and secrets are first-class, privacy-isolated objects. User identity resolution across channels. Secrets with optional AES-256-GCM at-rest encryption.
15
+ - **Security** Input sanitization, field length enforcement, audit logging, and HMAC webhook verification.
16
+ - **Self-updating** Built-in update checker with configurable policies and maintenance windows.
17
+
18
+ ## Packages
19
+
20
+ | Package | Description |
21
+ |---------|-------------|
22
+ | [`@botinabox/core`](packages/core) | Core framework — config, data, hooks, LLM, orchestration, chat, security |
23
+ | [`@botinabox/shared`](packages/shared) | Shared types, interfaces, and constants (zero dependencies) |
24
+ | [`@botinabox/cli`](packages/cli) | CLI tool for scaffolding new projects |
25
+ | [`@botinabox/provider-anthropic`](packages/providers/anthropic) | Anthropic Claude provider |
26
+ | [`@botinabox/provider-openai`](packages/providers/openai) | OpenAI GPT provider |
27
+ | [`@botinabox/provider-ollama`](packages/providers/ollama) | Ollama local model provider |
28
+ | [`@botinabox/channel-slack`](packages/channels/slack) | Slack channel adapter |
29
+ | [`@botinabox/channel-discord`](packages/channels/discord) | Discord channel adapter |
30
+ | [`@botinabox/channel-webhook`](packages/channels/webhook) | Webhook channel adapter with HMAC verification |
31
+
32
+ ## Quick Start
33
+
34
+ ### Prerequisites
35
+
36
+ - Node.js 20+
37
+ - pnpm 9+
38
+
39
+ ### Install
19
40
 
20
41
  ```bash
21
- npm install botinabox
42
+ git clone https://github.com/automated-industries/botinabox.git
43
+ cd botinabox
44
+ pnpm install
45
+ pnpm build
22
46
  ```
23
47
 
24
- Install peer dependencies for the providers you need:
48
+ ### Create a Project
25
49
 
26
50
  ```bash
27
- # For Anthropic
28
- npm install @anthropic-ai/sdk
51
+ npx botinabox init my-bot
52
+ cd my-bot
53
+ ```
29
54
 
30
- # For OpenAI
31
- npm install openai
55
+ This generates a project with a config file, environment template, and entry point.
56
+
57
+ ### Configure
58
+
59
+ Edit `botinabox.config.yml`:
60
+
61
+ ```yaml
62
+ data:
63
+ path: ./data/bot.db
64
+ walMode: true
65
+
66
+ channels:
67
+ slack:
68
+ enabled: true
69
+ botToken: ${SLACK_BOT_TOKEN}
70
+
71
+ providers:
72
+ anthropic:
73
+ enabled: true
74
+ apiKey: ${ANTHROPIC_API_KEY}
75
+
76
+ agents:
77
+ - slug: assistant
78
+ name: Assistant
79
+ adapter: api
80
+ model: smart
81
+
82
+ models:
83
+ default: claude-sonnet-4-6
84
+ aliases:
85
+ fast: claude-haiku-4-5
86
+ smart: claude-opus-4-6
87
+ balanced: claude-sonnet-4-6
88
+ routing:
89
+ conversation: fast
90
+ task_execution: smart
91
+ classification: fast
92
+ fallbackChain: []
93
+ ```
94
+
95
+ Set environment variables in `.env`:
32
96
 
33
- # For Google connectors
34
- npm install googleapis
97
+ ```bash
98
+ ANTHROPIC_API_KEY=your_key_here
99
+ SLACK_BOT_TOKEN=xoxb-your-token
35
100
  ```
36
101
 
37
- ## Quick Start
102
+ ### Run
38
103
 
39
104
  ```typescript
40
- import {
41
- HookBus,
42
- DataStore,
43
- defineCoreTables,
44
- AgentRegistry,
45
- TaskQueue,
46
- RunManager,
47
- } from 'botinabox';
48
-
49
- // 1. Create core services
105
+ import { HookBus } from '@botinabox/core';
106
+ import { loadConfig } from '@botinabox/core';
107
+ import { DataStore, defineCoreTables } from '@botinabox/core';
108
+ import { ProviderRegistry, ModelRouter } from '@botinabox/core';
109
+ import { AgentRegistry, TaskQueue, RunManager } from '@botinabox/core';
110
+ import { ChannelRegistry, MessagePipeline } from '@botinabox/core';
111
+ import createAnthropicProvider from '@botinabox/provider-anthropic';
112
+ import createSlackAdapter from '@botinabox/channel-slack';
113
+
114
+ // Load config
115
+ const { config } = loadConfig({ configPath: 'botinabox.config.yml' });
116
+
117
+ // Initialize systems
50
118
  const hooks = new HookBus();
51
- const db = new DataStore({ dbPath: './data/bot.db', wal: true, hooks });
52
-
53
- // 2. Define tables and initialize
119
+ const db = new DataStore({ dbPath: config.data.path, wal: config.data.walMode, hooks });
54
120
  defineCoreTables(db);
55
- await db.init();
121
+ db.init();
56
122
 
57
- // 3. Set up orchestration
123
+ // LLM providers
124
+ const providers = new ProviderRegistry();
125
+ providers.register(createAnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY! }));
126
+ const router = new ModelRouter(providers, config.models);
127
+
128
+ // Channels
129
+ const channels = new ChannelRegistry();
130
+ channels.register(createSlackAdapter(), config.channels.slack);
131
+
132
+ // Orchestration
58
133
  const agents = new AgentRegistry(db, hooks);
59
134
  const tasks = new TaskQueue(db, hooks);
60
135
  const runs = new RunManager(db, hooks);
136
+ const pipeline = new MessagePipeline(hooks, agents, tasks, config);
61
137
 
62
- // 4. Register an agent
63
- const agentId = await agents.register({
64
- slug: 'assistant',
65
- name: 'Assistant',
66
- adapter: 'api',
67
- role: 'general',
68
- });
69
-
70
- // 5. Listen for task creation
71
- hooks.register('task.created', async (ctx) => {
72
- console.log(`Task created: ${ctx.taskId}`);
73
- });
74
-
75
- // 6. Create a task
76
- const taskId = await tasks.create({
77
- title: 'Summarize the quarterly report',
78
- description: 'Read the Q4 report and produce a 3-paragraph summary.',
79
- assignee_id: agentId,
80
- priority: 3,
81
- });
82
-
83
- // 7. Wire up task completion hooks
84
- hooks.register('run.completed', async (ctx) => {
85
- console.log(`Run finished for task ${ctx.taskId}, exit code: ${ctx.exitCode}`);
86
- });
138
+ // Start
139
+ tasks.startPolling();
140
+ await channels.start();
87
141
  ```
88
142
 
89
- ## Subpath Exports
90
-
91
- | Import path | Description |
92
- |---|---|
93
- | `botinabox` | Core framework -- HookBus, DataStore, AgentRegistry, TaskQueue, RunManager, ChannelRegistry, MessagePipeline, Scheduler, config, security, and all shared types |
94
- | `botinabox/anthropic` | Anthropic Claude provider (`createAnthropicProvider`) |
95
- | `botinabox/openai` | OpenAI GPT provider (`createOpenAIProvider`) |
96
- | `botinabox/ollama` | Ollama local model provider (`createOllamaProvider`) |
97
- | `botinabox/slack` | Slack channel adapter (`SlackAdapter`) |
98
- | `botinabox/discord` | Discord channel adapter (`DiscordAdapter`) |
99
- | `botinabox/webhook` | Webhook channel adapter with HMAC verification (`WebhookAdapter`) |
100
- | `botinabox/google` | Google connectors -- Gmail and Calendar via OAuth2 |
101
-
102
143
  ## Architecture
103
144
 
104
145
  ```
105
- +-------------------------------------+
106
- | Channel Adapters |
107
- | Slack . Discord . Webhook |
108
- +--------------+-----------------------+
109
- | InboundMessage
110
- +--------------v-----------------------+
111
- | Message Pipeline |
112
- | routing . policies . sessions |
113
- +--------------+-----------------------+
114
- | Task
115
- +--------------v-----------------------+
116
- | Task Queue |
117
- | priority . retry . followup chains |
118
- +--------------+-----------------------+
119
- |
120
- +--------------v-----------------------+
121
- | Run Manager |
122
- | locking . retries . cost tracking |
123
- +--------------+-----------------------+
124
- |
125
- +--------------------+--------------------+
126
- v v v
127
- +------------------+ +------------------+ +---------------+
128
- | CLI Adapter | | API Adapter | | Custom |
129
- | (subprocess) | | (LLM + tools) | | Adapters |
130
- +------------------+ +--------+----------+ +---------------+
131
- |
132
- +--------------v-----------------------+
133
- | LLM Layer |
134
- | ProviderRegistry . ModelRouter |
135
- | BudgetController . Tool Loop |
136
- +--------------+-----------------------+
137
- |
138
- +--------------------+-------------------+
139
- v v v
140
- +---------------+ +---------------+ +---------------+
141
- | Anthropic | | OpenAI | | Ollama |
142
- +---------------+ +---------------+ +---------------+
146
+ ┌─────────────────────────────────────┐
147
+ Channel Adapters
148
+ Slack · Discord · Webhook
149
+ └──────────────┬──────────────────────┘
150
+ InboundMessage
151
+ ┌──────────────▼──────────────────────┐
152
+ Message Pipeline
153
+ routing · policies · sessions
154
+ └──────────────┬──────────────────────┘
155
+ Task
156
+ ┌──────────────▼──────────────────────┐
157
+ Task Queue
158
+ priority · retry · followup chains
159
+ └──────────────┬──────────────────────┘
160
+
161
+ ┌──────────────▼──────────────────────┐
162
+ Run Manager
163
+ locking · retries · cost tracking
164
+ └──────────────┬──────────────────────┘
165
+
166
+ ┌────────────────────┼────────────────────┐
167
+
168
+ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐
169
+ CLI Adapter API Adapter Custom
170
+ (subprocess) (LLM + tools) Adapters
171
+ └─────────────────┘ └────────┬─────────┘ └──────────────┘
172
+
173
+ ┌─────────────▼───────────────────────┐
174
+ LLM Layer
175
+ ProviderRegistry · ModelRouter
176
+ CostTracker · Tool Loop
177
+ └─────────────┬───────────────────────┘
178
+
179
+ ┌───────────────────┼───────────────────┐
180
+ ▼ ▼
181
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
182
+ Anthropic │ │ OpenAI Ollama
183
+ └──────────────┘ └──────────────┘ └──────────────┘
143
184
  ```
144
185
 
145
- Cross-cutting concerns -- **HookBus** (events), **DataStore** (persistence), **Security** (sanitization + audit) -- connect all layers.
186
+ Cross-cutting concerns **HookBus** (events), **DataStore** (persistence), **Security** (sanitization + audit) connect all layers.
146
187
 
147
- ## Core Concepts
188
+ ## Documentation
148
189
 
149
- **HookBus** is the central event bus. Handlers subscribe to named events with optional priority ordering and payload filters. Errors in one handler never block others. Use it to decouple layers -- the task queue emits `task.created`, the run manager emits `run.completed`, channels emit `message.inbound`, and your application code listens to whichever events it needs.
190
+ - [Getting Started](docs/getting-started.md) Installation, project setup, first bot
191
+ - [Configuration](docs/configuration.md) — Full config reference
192
+ - [Architecture](docs/architecture.md) — System design and patterns
193
+ - [Providers](docs/providers.md) — LLM provider setup and custom providers
194
+ - [Channels](docs/channels.md) — Channel adapter setup and custom adapters
195
+ - [Orchestration](docs/orchestration.md) — Agents, tasks, workflows, and budget controls
196
+ - [API Reference](docs/api-reference.md) — Complete API documentation
150
197
 
151
- **DataStore** wraps [latticesql](https://github.com/automated-industries/lattice) to provide schema-driven SQLite persistence. You call `db.define()` to register table schemas, then `db.init()` to create them. It supports insert, update, upsert, get, query, delete, and migrations. WAL mode is enabled by default for concurrent read access.
198
+ ## Development
152
199
 
153
- **AgentRegistry** manages the lifecycle of agents -- registration, status transitions (idle/running/paused/terminated), configuration revisions, and activity logging. Each agent has a slug, name, adapter type, role, and optional budget. Agents are stored in the database and can be seeded from config on startup.
200
+ ```bash
201
+ # Install dependencies
202
+ pnpm install
154
203
 
155
- **TaskQueue** is a priority-ordered work queue backed by SQLite. Tasks have a title, description, assignee, priority (1-10), and support retry policies and followup chains. Chain depth is enforced to prevent infinite recursion. The queue emits `task.created` on the HookBus and supports polling for stale tasks.
204
+ # Build all packages
205
+ pnpm build
156
206
 
157
- **RunManager** handles task execution lifecycle. It acquires a per-agent lock, creates a run record, delegates to an execution adapter (API or CLI), and records the result including exit code, cost, and token usage. Failed runs trigger retry logic with exponential backoff.
207
+ # Run all tests
208
+ pnpm test:run
158
209
 
159
- **ChannelRegistry** manages channel adapter connections. Register adapters (Slack, Discord, webhook) with their config, then call `start()` to connect them all. Supports hot reconfiguration, health checks, and graceful shutdown.
210
+ # Type-check
211
+ pnpm typecheck
212
+ ```
160
213
 
161
- **MessagePipeline** routes inbound messages from channels to the task queue. It resolves the sender to a user identity, picks the right agent based on channel bindings, applies policy checks (allowlists, mention gates), and creates a task for the assigned agent.
214
+ ### Project Structure
162
215
 
163
- **Scheduler** provides database-backed job scheduling with cron expressions. Register recurring or one-time schedules that emit hook events when they fire. The scheduler polls for due jobs and emits the schedule's `action` as a hook event with its configured payload.
216
+ ```
217
+ botinabox/
218
+ ├── packages/
219
+ │ ├── core/ # Core framework
220
+ │ │ └── src/
221
+ │ │ ├── config/ # YAML config loader + validation
222
+ │ │ ├── data/ # SQLite ORM, migrations, entity rendering
223
+ │ │ ├── hooks/ # Event bus
224
+ │ │ ├── llm/ # Provider registry, model router, cost tracking
225
+ │ │ ├── chat/ # Channel registry, message pipeline, sessions
226
+ │ │ ├── orchestrator/ # Agents, tasks, runs, workflows, adapters
227
+ │ │ ├── security/ # Sanitizer, audit, column validation
228
+ │ │ └── update/ # Self-update system
229
+ │ ├── shared/ # Types and constants (zero deps)
230
+ │ ├── cli/ # CLI scaffolding tool
231
+ │ ├── providers/
232
+ │ │ ├── anthropic/ # Claude models
233
+ │ │ ├── openai/ # GPT models
234
+ │ │ └── ollama/ # Local models
235
+ │ └── channels/
236
+ │ ├── slack/ # Slack adapter
237
+ │ ├── discord/ # Discord adapter
238
+ │ └── webhook/ # Webhook adapter + HMAC
239
+ ├── package.json
240
+ ├── pnpm-workspace.yaml
241
+ └── tsconfig.json
242
+ ```
164
243
 
165
- ## Documentation
244
+ ## Staying up to date
245
+
246
+ **CLI users:** The `botinabox` CLI checks for new versions automatically and prints a notice when an update is available. Run `botinabox update` to upgrade in place. Alternatively, use `npx botinabox` to always run the latest version without a global install.
166
247
 
167
- - [Getting Started](docs/getting-started.md) -- Installation, project setup, first bot
168
- - [Configuration](docs/configuration.md) -- Full config reference
169
- - [Architecture](docs/architecture.md) -- System design and patterns
170
- - [Providers](docs/providers.md) -- LLM provider setup and custom providers
171
- - [Channels](docs/channels.md) -- Channel adapter setup and custom adapters
172
- - [Orchestration](docs/orchestration.md) -- Agents, tasks, workflows, and budget controls
173
- - [API Reference](docs/api-reference.md) -- Complete API documentation
248
+ **Library consumers:** By default, `npm install botinabox` adds a `^` semver range to your `package.json`, so patch and minor updates are picked up on your next `npm install`. For fully automated dependency updates, set up [Dependabot](https://docs.github.com/en/code-security/dependabot) or [Renovate](https://github.com/renovatebot/renovate) they'll create PRs in your repo whenever a new version is published.
174
249
 
175
250
  ## License
176
251
 
package/dist/index.d.ts CHANGED
@@ -305,6 +305,7 @@ declare const EVENTS: {
305
305
  declare const DEFAULTS: {
306
306
  readonly TASK_POLL_INTERVAL_MS: 30000;
307
307
  readonly NOTIFICATION_POLL_INTERVAL_MS: 5000;
308
+ readonly HEARTBEAT_INTERVAL_MS: 300000;
308
309
  readonly ORPHAN_REAP_INTERVAL_MS: 300000;
309
310
  readonly STALE_RUN_THRESHOLD_MS: 1800000;
310
311
  readonly STALE_TASK_AGE_MS: 7200000;
@@ -1319,6 +1320,23 @@ declare class NdjsonLogger {
1319
1320
  close(): void;
1320
1321
  }
1321
1322
 
1323
+ /**
1324
+ * @deprecated Use {@link Scheduler} from `botinabox` instead.
1325
+ * HeartbeatScheduler uses in-memory setInterval which loses state on restart.
1326
+ * The Scheduler class uses database-backed schedules with cron expressions.
1327
+ */
1328
+ declare class HeartbeatScheduler {
1329
+ private wakeupQueue;
1330
+ private hooks;
1331
+ private timers;
1332
+ constructor(wakeupQueue: WakeupQueue, hooks: HookBus);
1333
+ start(agents: Array<{
1334
+ id: string;
1335
+ heartbeat_config: string;
1336
+ }>): void;
1337
+ stop(): void;
1338
+ }
1339
+
1322
1340
  /**
1323
1341
  * Scheduler — database-backed job scheduling with cron expressions.
1324
1342
  *
@@ -1326,7 +1344,7 @@ declare class NdjsonLogger {
1326
1344
  * it emits the schedule's `action` as a hook event with the
1327
1345
  * `action_config` payload. Consumers subscribe to handle the action.
1328
1346
  *
1329
- * Supports one-time and recurring use cases.
1347
+ * Replaces HeartbeatScheduler for recurring use cases.
1330
1348
  */
1331
1349
 
1332
1350
  interface ScheduleDef {
@@ -1549,4 +1567,4 @@ declare function isLoginRequired(stdout: string): boolean;
1549
1567
  /** Rewrite local image paths to prevent CLI auto-embedding as vision content. */
1550
1568
  declare function deactivateLocalImagePaths(prompt: string): string;
1551
1569
 
1552
- export { AGENT_STATUSES, type AgentConfig, type AgentDefinition, type AgentFilter, type AgentRecord, AgentRegistry, type AgentStatus, ApiExecutionAdapter, AuditEmitter, type AuditEvent, BackupManager, type BotConfig, type BudgetCheck, type BudgetConfig, BudgetController, CORE_MIGRATIONS, ChannelAdapter, ChannelRegistry, ChannelRegistryError, ChatMessage, ChatSessionManager, CliExecutionAdapter, type ColumnValidator, ColumnValidatorImpl, type ConfigLoadError, type ConfigLoadResult, ConnectorConfig, DEFAULTS, DEFAULT_CONFIG, type DataConfig, DataStore, DataStoreError, type DomainEntityContextOptions, type DomainSchemaOptions, EVENTS, type EntityColumnDef, type EntityConfig, type EntityContextDef, type EntityFileSpec, type EntitySource, type ExecutionAdapter, type Filter, HealthStatus, HookBus, type HookHandler, type HookOptions, type HookRegistration, InboundMessage, LLMProvider, MAX_CHAIN_DEPTH, MessagePipeline, type ModelConfig, ModelInfo, ModelRouter, NdjsonLogger, NotificationQueue, type PackageMigration, type PackageUpdate, type ParsedStream, type PkLookup, ProviderRegistry, type QueryOptions, RUN_STATUSES, type RelationDef, type RenderConfig, ResolvedModel, type RetryPolicy, type Row, type RunContext, RunManager, type RunResult, type RunStatus, type SanitizerOptions, type Schedule, type ScheduleDef, Scheduler, type SchemaError, type SecretInput, type SecretMeta, SecretStore, type SecurityConfig, type SeedItem, SessionKey, SessionManager, type SqliteAdapter, type StepRef, TASK_STATUSES, type TableDefinition, type TableInfoRow, type TaskDefinition, TaskQueue, type TaskRecord, type TaskStatus, TokenUsage, type Unsubscribe, UpdateChecker, type UpdateConfig, UpdateManager, type UpdateManifest, type UsageSummary, type User, type UserInput, UserRegistry, WakeupQueue, type WorkflowConfigEntry, type WorkflowDefinition$1 as WorkflowDefinition, WorkflowEngine, type WorkflowRunRecord, type WorkflowRunStatus, type WorkflowStep$1 as WorkflowStep, type WorkflowStepConfig, type WorkflowTrigger, _resetConfig, areDependenciesMet, buildAgentBindings, buildChainOrigin, buildProcessEnv, checkAllowlist, checkChainDepth, checkMentionGate, chunkText, classifyUpdate, compareVersions, createConfigRevision, deactivateLocalImagePaths, defineCoreEntityContexts, defineCoreTables, defineDomainEntityContexts, defineDomainTables, detectCycle, discoverChannels, discoverProviders, formatText, getConfig, initConfig, interpolate, interpolateEnv, isLoginRequired, isMaxTurns, loadConfig, parseClaudeStream, parseVersion, runPackageMigrations, sanitize, topologicalSort, validateConfig };
1570
+ export { AGENT_STATUSES, type AgentConfig, type AgentDefinition, type AgentFilter, type AgentRecord, AgentRegistry, type AgentStatus, ApiExecutionAdapter, AuditEmitter, type AuditEvent, BackupManager, type BotConfig, type BudgetCheck, type BudgetConfig, BudgetController, CORE_MIGRATIONS, ChannelAdapter, ChannelRegistry, ChannelRegistryError, ChatMessage, ChatSessionManager, CliExecutionAdapter, type ColumnValidator, ColumnValidatorImpl, type ConfigLoadError, type ConfigLoadResult, ConnectorConfig, DEFAULTS, DEFAULT_CONFIG, type DataConfig, DataStore, DataStoreError, type DomainEntityContextOptions, type DomainSchemaOptions, EVENTS, type EntityColumnDef, type EntityConfig, type EntityContextDef, type EntityFileSpec, type EntitySource, type ExecutionAdapter, type Filter, HealthStatus, HeartbeatScheduler, HookBus, type HookHandler, type HookOptions, type HookRegistration, InboundMessage, LLMProvider, MAX_CHAIN_DEPTH, MessagePipeline, type ModelConfig, ModelInfo, ModelRouter, NdjsonLogger, NotificationQueue, type PackageMigration, type PackageUpdate, type ParsedStream, type PkLookup, ProviderRegistry, type QueryOptions, RUN_STATUSES, type RelationDef, type RenderConfig, ResolvedModel, type RetryPolicy, type Row, type RunContext, RunManager, type RunResult, type RunStatus, type SanitizerOptions, type Schedule, type ScheduleDef, Scheduler, type SchemaError, type SecretInput, type SecretMeta, SecretStore, type SecurityConfig, type SeedItem, SessionKey, SessionManager, type SqliteAdapter, type StepRef, TASK_STATUSES, type TableDefinition, type TableInfoRow, type TaskDefinition, TaskQueue, type TaskRecord, type TaskStatus, TokenUsage, type Unsubscribe, UpdateChecker, type UpdateConfig, UpdateManager, type UpdateManifest, type UsageSummary, type User, type UserInput, UserRegistry, WakeupQueue, type WorkflowConfigEntry, type WorkflowDefinition$1 as WorkflowDefinition, WorkflowEngine, type WorkflowRunRecord, type WorkflowRunStatus, type WorkflowStep$1 as WorkflowStep, type WorkflowStepConfig, type WorkflowTrigger, _resetConfig, areDependenciesMet, buildAgentBindings, buildChainOrigin, buildProcessEnv, checkAllowlist, checkChainDepth, checkMentionGate, chunkText, classifyUpdate, compareVersions, createConfigRevision, deactivateLocalImagePaths, defineCoreEntityContexts, defineCoreTables, defineDomainEntityContexts, defineDomainTables, detectCycle, discoverChannels, discoverProviders, formatText, getConfig, initConfig, interpolate, interpolateEnv, isLoginRequired, isMaxTurns, loadConfig, parseClaudeStream, parseVersion, runPackageMigrations, sanitize, topologicalSort, validateConfig };
package/dist/index.js CHANGED
@@ -35,6 +35,8 @@ var EVENTS = {
35
35
  var DEFAULTS = {
36
36
  TASK_POLL_INTERVAL_MS: 3e4,
37
37
  NOTIFICATION_POLL_INTERVAL_MS: 5e3,
38
+ HEARTBEAT_INTERVAL_MS: 3e5,
39
+ // 5 minutes
38
40
  ORPHAN_REAP_INTERVAL_MS: 3e5,
39
41
  // 5 minutes
40
42
  STALE_RUN_THRESHOLD_MS: 18e5,
@@ -1153,17 +1155,15 @@ var DataStore = class {
1153
1155
  outputFile: def.indexFile,
1154
1156
  render: def.indexRender ?? ((rows) => {
1155
1157
  const active = rows.filter((r) => r.deleted_at == null);
1156
- const dir = def.directory;
1157
- const title = dir.charAt(0).toUpperCase() + dir.slice(1);
1158
+ const title = def.directory.charAt(0).toUpperCase() + def.directory.slice(1);
1158
1159
  if (!active.length) return `# ${title}
1159
1160
 
1160
1161
  None.
1161
1162
  `;
1162
1163
  const lines = active.map((r) => {
1163
- const slug = String(r[def.slugColumn] ?? r.name ?? r.id ?? "unknown");
1164
- const name2 = String(r.name ?? slug);
1164
+ const name2 = String(r.name ?? r[def.slugColumn] ?? r.id ?? "unknown");
1165
1165
  const status = r.status ? ` (${r.status})` : "";
1166
- return `- [${name2}](${dir}/${slug}/)${status}`;
1166
+ return `- **${name2}**${status}`;
1167
1167
  });
1168
1168
  return `# ${title}
1169
1169
 
@@ -3406,6 +3406,38 @@ var NdjsonLogger = class {
3406
3406
  }
3407
3407
  };
3408
3408
 
3409
+ // src/core/orchestrator/heartbeat-scheduler.ts
3410
+ var HeartbeatScheduler = class {
3411
+ constructor(wakeupQueue, hooks) {
3412
+ this.wakeupQueue = wakeupQueue;
3413
+ this.hooks = hooks;
3414
+ }
3415
+ wakeupQueue;
3416
+ hooks;
3417
+ timers = /* @__PURE__ */ new Map();
3418
+ start(agents) {
3419
+ for (const agent of agents) {
3420
+ let config;
3421
+ try {
3422
+ config = JSON.parse(agent.heartbeat_config);
3423
+ } catch {
3424
+ continue;
3425
+ }
3426
+ if (!config.enabled || !config.intervalSec) continue;
3427
+ const timer = setInterval(() => {
3428
+ void this.wakeupQueue.enqueue(agent.id, "heartbeat");
3429
+ }, config.intervalSec * 1e3);
3430
+ this.timers.set(agent.id, timer);
3431
+ }
3432
+ }
3433
+ stop() {
3434
+ for (const timer of this.timers.values()) {
3435
+ clearInterval(timer);
3436
+ }
3437
+ this.timers.clear();
3438
+ }
3439
+ };
3440
+
3409
3441
  // src/core/orchestrator/scheduler.ts
3410
3442
  import cronParser from "cron-parser";
3411
3443
  import { v4 as uuid } from "uuid";
@@ -4160,6 +4192,7 @@ export {
4160
4192
  DataStore,
4161
4193
  DataStoreError,
4162
4194
  EVENTS,
4195
+ HeartbeatScheduler,
4163
4196
  HookBus,
4164
4197
  MAX_CHAIN_DEPTH,
4165
4198
  MessagePipeline,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botinabox",
3
- "version": "0.6.0",
3
+ "version": "1.0.0",
4
4
  "description": "Bot in a Box — framework for building multi-agent bots",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -59,7 +59,7 @@
59
59
  "@types/uuid": "^10.0.0",
60
60
  "ajv": "^8.17.1",
61
61
  "cron-parser": "^4.9.0",
62
- "latticesql": "^0.18.0",
62
+ "latticesql": "^1.0.0",
63
63
  "uuid": "^13.0.0",
64
64
  "yaml": "^2.7.0"
65
65
  },