botinabox 0.3.1 → 0.4.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/dist/index.d.ts CHANGED
@@ -466,6 +466,8 @@ declare class ChannelRegistry {
466
466
  * Run health checks on all registered adapters.
467
467
  */
468
468
  healthCheck(): Promise<Record<string, HealthStatus>>;
469
+ /** Check if an adapter is registered. */
470
+ has(id: string): boolean;
469
471
  /** Get an adapter by ID. */
470
472
  get(id: string): ChannelAdapter | undefined;
471
473
  /** List all registered adapters. */
@@ -550,6 +552,7 @@ type EntitySource = {
550
552
  remoteKey: string;
551
553
  remoteTable: string;
552
554
  filters?: Filter[];
555
+ softDelete?: boolean;
553
556
  orderBy?: string;
554
557
  limit?: number;
555
558
  } | {
@@ -986,6 +989,69 @@ declare const CORE_MIGRATIONS: Array<{
986
989
  */
987
990
  declare function defineCoreEntityContexts(db: DataStore): void;
988
991
 
992
+ /**
993
+ * Options for domain table generation.
994
+ * Enable/disable optional tables based on your app's needs.
995
+ */
996
+ interface DomainSchemaOptions {
997
+ /** Include client + invoice tables (default: true) */
998
+ clients?: boolean;
999
+ /** Include repository table (default: true) */
1000
+ repositories?: boolean;
1001
+ /** Include file table (default: true) */
1002
+ files?: boolean;
1003
+ /** Include channel table (default: true) */
1004
+ channels?: boolean;
1005
+ /** Include rule table + junction tables (default: true) */
1006
+ rules?: boolean;
1007
+ /** Include event audit log (default: true) */
1008
+ events?: boolean;
1009
+ }
1010
+ /**
1011
+ * Define standard domain tables that most multi-agent apps need.
1012
+ * Call after defineCoreTables() and before db.init().
1013
+ *
1014
+ * Provides: org, project, + optional client, invoice, repository,
1015
+ * file, channel, rule, event tables with appropriate junction tables.
1016
+ *
1017
+ * @example
1018
+ * ```ts
1019
+ * defineCoreTables(db);
1020
+ * defineDomainTables(db); // all tables
1021
+ * defineDomainTables(db, { clients: false }); // skip client/invoice
1022
+ * ```
1023
+ */
1024
+ declare function defineDomainTables(db: DataStore, options?: DomainSchemaOptions): void;
1025
+
1026
+ /**
1027
+ * Options for domain entity context generation.
1028
+ * Match the options used in defineDomainTables().
1029
+ */
1030
+ interface DomainEntityContextOptions {
1031
+ clients?: boolean;
1032
+ repositories?: boolean;
1033
+ files?: boolean;
1034
+ channels?: boolean;
1035
+ rules?: boolean;
1036
+ }
1037
+ /**
1038
+ * Define entity context rendering for standard domain tables.
1039
+ * Call after defineDomainTables() and defineCoreTables().
1040
+ *
1041
+ * Renders per-entity directories with context files for:
1042
+ * org, project, + optional client, file, channel entities.
1043
+ * Also adds PROJECTS.md, RULES.md, SKILLS.md, REPOS.md to agent context.
1044
+ *
1045
+ * @example
1046
+ * ```ts
1047
+ * defineCoreTables(db);
1048
+ * defineDomainTables(db);
1049
+ * defineCoreEntityContexts(db); // agents, users, skills
1050
+ * defineDomainEntityContexts(db); // org, project, client, file, channel
1051
+ * ```
1052
+ */
1053
+ declare function defineDomainEntityContexts(db: DataStore, options?: DomainEntityContextOptions): void;
1054
+
989
1055
  interface SanitizerOptions {
990
1056
  fieldLengthLimits?: Record<string, number>;
991
1057
  truncateSuffix?: string;
@@ -1047,6 +1113,20 @@ declare class AuditEmitter {
1047
1113
  emit(event: AuditEvent): void;
1048
1114
  }
1049
1115
 
1116
+ /**
1117
+ * Build a clean environment for spawned subprocesses.
1118
+ * Strips secrets and passes only safe system variables.
1119
+ * Used by the CLI execution adapter when spawning agent processes.
1120
+ */
1121
+ /**
1122
+ * Build a filtered environment for subprocess execution.
1123
+ * Only passes explicitly allowed variables — all secrets are stripped.
1124
+ *
1125
+ * @param allowedKeys - Additional keys to allow beyond the defaults
1126
+ * @param inject - Extra key-value pairs to inject into the env
1127
+ */
1128
+ declare function buildProcessEnv(allowedKeys?: string[], inject?: Record<string, string>): Record<string, string>;
1129
+
1050
1130
  interface PackageUpdate {
1051
1131
  name: string;
1052
1132
  installedVersion: string;
@@ -1373,4 +1453,36 @@ declare class SecretStore {
1373
1453
  private _toMeta;
1374
1454
  }
1375
1455
 
1376
- 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, DEFAULTS, DEFAULT_CONFIG, type DataConfig, DataStore, DataStoreError, 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 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 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 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, checkAllowlist, checkChainDepth, checkMentionGate, chunkText, classifyUpdate, compareVersions, createConfigRevision, defineCoreEntityContexts, defineCoreTables, detectCycle, discoverChannels, discoverProviders, formatText, getConfig, initConfig, interpolate, interpolateEnv, loadConfig, parseVersion, runPackageMigrations, sanitize, topologicalSort, validateConfig };
1456
+ /**
1457
+ * Parse Claude CLI NDJSON (stream-json) output into structured results.
1458
+ * Used by the CLI execution adapter to extract session info, costs,
1459
+ * token usage, and text output from Claude CLI subprocess output.
1460
+ */
1461
+ interface ParsedStream {
1462
+ sessionId: string | null;
1463
+ model: string | null;
1464
+ costUsd: number | null;
1465
+ usage: UsageSummary | null;
1466
+ summary: string;
1467
+ isError: boolean;
1468
+ errorMessage: string | null;
1469
+ stopReason: string | null;
1470
+ }
1471
+ interface UsageSummary {
1472
+ inputTokens: number;
1473
+ cachedInputTokens: number;
1474
+ outputTokens: number;
1475
+ }
1476
+ /**
1477
+ * Parse Claude CLI NDJSON output into a structured result.
1478
+ * Handles init, assistant, and result event types.
1479
+ */
1480
+ declare function parseClaudeStream(stdout: string): ParsedStream;
1481
+ /** Check if the run stopped due to max turns. */
1482
+ declare function isMaxTurns(parsed: ParsedStream): boolean;
1483
+ /** Check if Claude CLI requires login. */
1484
+ declare function isLoginRequired(stdout: string): boolean;
1485
+ /** Rewrite local image paths to prevent CLI auto-embedding as vision content. */
1486
+ declare function deactivateLocalImagePaths(prompt: string): string;
1487
+
1488
+ 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, 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 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
@@ -585,6 +585,10 @@ var ChannelRegistry = class {
585
585
  }
586
586
  return results;
587
587
  }
588
+ /** Check if an adapter is registered. */
589
+ has(id) {
590
+ return this.adapters.has(id);
591
+ }
588
592
  /** Get an adapter by ID. */
589
593
  get(id) {
590
594
  return this.adapters.get(id)?.adapter;
@@ -923,6 +927,9 @@ var NotificationQueue = class {
923
927
  * Returns the notification ID.
924
928
  */
925
929
  async enqueue(channel, recipient, payload) {
930
+ if (!this.channelRegistry.has(channel)) {
931
+ throw new Error(`No registered adapter for channel: ${channel}`);
932
+ }
926
933
  const row = await this.db.insert("notifications", {
927
934
  channel,
928
935
  recipient_id: recipient,
@@ -2767,8 +2774,9 @@ var TaskQueue = class {
2767
2774
  )
2768
2775
  )
2769
2776
  });
2770
- await this.hooks.emit("task.created", { taskId: row["id"], title: task.title });
2771
- return row["id"];
2777
+ const taskId = row["id"];
2778
+ void this.hooks.emit("task.created", { taskId, title: task.title });
2779
+ return taskId;
2772
2780
  }
2773
2781
  async update(id, changes) {
2774
2782
  await this.db.update("tasks", { id }, {
@@ -2905,6 +2913,11 @@ var RunManager = class {
2905
2913
  }
2906
2914
  }
2907
2915
  } else {
2916
+ await this.db.update("tasks", { id: taskId }, {
2917
+ status: "done",
2918
+ result: result.output,
2919
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
2920
+ });
2908
2921
  const task = await this.db.get("tasks", { id: taskId });
2909
2922
  if (task && task["followup_agent_id"]) {
2910
2923
  const chainDepth = (task["chain_depth"] ?? 0) + 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botinabox",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Bot in a Box — framework for building multi-agent bots",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",