@botcord/daemon 0.1.1

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 (149) hide show
  1. package/dist/activity-tracker.d.ts +43 -0
  2. package/dist/activity-tracker.js +110 -0
  3. package/dist/adapters/runtimes.d.ts +14 -0
  4. package/dist/adapters/runtimes.js +18 -0
  5. package/dist/agent-discovery.d.ts +81 -0
  6. package/dist/agent-discovery.js +181 -0
  7. package/dist/agent-workspace.d.ts +31 -0
  8. package/dist/agent-workspace.js +221 -0
  9. package/dist/config.d.ts +116 -0
  10. package/dist/config.js +180 -0
  11. package/dist/control-channel.d.ts +99 -0
  12. package/dist/control-channel.js +388 -0
  13. package/dist/cross-room.d.ts +23 -0
  14. package/dist/cross-room.js +55 -0
  15. package/dist/daemon-config-map.d.ts +61 -0
  16. package/dist/daemon-config-map.js +153 -0
  17. package/dist/daemon.d.ts +123 -0
  18. package/dist/daemon.js +349 -0
  19. package/dist/doctor.d.ts +89 -0
  20. package/dist/doctor.js +191 -0
  21. package/dist/gateway/channel-manager.d.ts +54 -0
  22. package/dist/gateway/channel-manager.js +292 -0
  23. package/dist/gateway/channels/botcord.d.ts +93 -0
  24. package/dist/gateway/channels/botcord.js +510 -0
  25. package/dist/gateway/channels/index.d.ts +2 -0
  26. package/dist/gateway/channels/index.js +1 -0
  27. package/dist/gateway/channels/sanitize.d.ts +20 -0
  28. package/dist/gateway/channels/sanitize.js +56 -0
  29. package/dist/gateway/dispatcher.d.ts +73 -0
  30. package/dist/gateway/dispatcher.js +431 -0
  31. package/dist/gateway/gateway.d.ts +87 -0
  32. package/dist/gateway/gateway.js +158 -0
  33. package/dist/gateway/index.d.ts +15 -0
  34. package/dist/gateway/index.js +15 -0
  35. package/dist/gateway/log.d.ts +9 -0
  36. package/dist/gateway/log.js +20 -0
  37. package/dist/gateway/router.d.ts +10 -0
  38. package/dist/gateway/router.js +48 -0
  39. package/dist/gateway/runtimes/claude-code.d.ts +30 -0
  40. package/dist/gateway/runtimes/claude-code.js +162 -0
  41. package/dist/gateway/runtimes/codex.d.ts +83 -0
  42. package/dist/gateway/runtimes/codex.js +272 -0
  43. package/dist/gateway/runtimes/gemini.d.ts +15 -0
  44. package/dist/gateway/runtimes/gemini.js +29 -0
  45. package/dist/gateway/runtimes/ndjson-stream.d.ts +43 -0
  46. package/dist/gateway/runtimes/ndjson-stream.js +169 -0
  47. package/dist/gateway/runtimes/probe.d.ts +17 -0
  48. package/dist/gateway/runtimes/probe.js +54 -0
  49. package/dist/gateway/runtimes/registry.d.ts +59 -0
  50. package/dist/gateway/runtimes/registry.js +94 -0
  51. package/dist/gateway/session-store.d.ts +39 -0
  52. package/dist/gateway/session-store.js +133 -0
  53. package/dist/gateway/types.d.ts +265 -0
  54. package/dist/gateway/types.js +1 -0
  55. package/dist/index.d.ts +2 -0
  56. package/dist/index.js +854 -0
  57. package/dist/log.d.ts +7 -0
  58. package/dist/log.js +44 -0
  59. package/dist/provision.d.ts +88 -0
  60. package/dist/provision.js +749 -0
  61. package/dist/room-context-fetcher.d.ts +18 -0
  62. package/dist/room-context-fetcher.js +101 -0
  63. package/dist/room-context.d.ts +53 -0
  64. package/dist/room-context.js +112 -0
  65. package/dist/sender-classify.d.ts +30 -0
  66. package/dist/sender-classify.js +32 -0
  67. package/dist/snapshot-writer.d.ts +37 -0
  68. package/dist/snapshot-writer.js +84 -0
  69. package/dist/status-render.d.ts +28 -0
  70. package/dist/status-render.js +97 -0
  71. package/dist/system-context.d.ts +57 -0
  72. package/dist/system-context.js +91 -0
  73. package/dist/turn-text.d.ts +36 -0
  74. package/dist/turn-text.js +57 -0
  75. package/dist/user-auth.d.ts +75 -0
  76. package/dist/user-auth.js +245 -0
  77. package/dist/working-memory.d.ts +46 -0
  78. package/dist/working-memory.js +274 -0
  79. package/package.json +39 -0
  80. package/src/__tests__/activity-tracker.test.ts +130 -0
  81. package/src/__tests__/agent-discovery.test.ts +191 -0
  82. package/src/__tests__/agent-workspace.test.ts +147 -0
  83. package/src/__tests__/control-channel.test.ts +327 -0
  84. package/src/__tests__/cross-room.test.ts +116 -0
  85. package/src/__tests__/daemon-config-map.test.ts +416 -0
  86. package/src/__tests__/daemon.test.ts +300 -0
  87. package/src/__tests__/device-code.test.ts +152 -0
  88. package/src/__tests__/doctor.test.ts +218 -0
  89. package/src/__tests__/protocol-core-reexport.test.ts +24 -0
  90. package/src/__tests__/provision.test.ts +922 -0
  91. package/src/__tests__/room-context.test.ts +233 -0
  92. package/src/__tests__/runtime-discovery.test.ts +173 -0
  93. package/src/__tests__/snapshot-writer.test.ts +141 -0
  94. package/src/__tests__/status-render.test.ts +137 -0
  95. package/src/__tests__/system-context.test.ts +315 -0
  96. package/src/__tests__/turn-text.test.ts +116 -0
  97. package/src/__tests__/user-auth.test.ts +125 -0
  98. package/src/__tests__/working-memory.test.ts +240 -0
  99. package/src/activity-tracker.ts +140 -0
  100. package/src/adapters/runtimes.ts +30 -0
  101. package/src/agent-discovery.ts +262 -0
  102. package/src/agent-workspace.ts +247 -0
  103. package/src/config.ts +290 -0
  104. package/src/control-channel.ts +455 -0
  105. package/src/cross-room.ts +89 -0
  106. package/src/daemon-config-map.ts +200 -0
  107. package/src/daemon.ts +478 -0
  108. package/src/doctor.ts +282 -0
  109. package/src/gateway/__tests__/.gitkeep +0 -0
  110. package/src/gateway/__tests__/botcord-channel.test.ts +480 -0
  111. package/src/gateway/__tests__/channel-manager.test.ts +475 -0
  112. package/src/gateway/__tests__/claude-code-adapter.test.ts +318 -0
  113. package/src/gateway/__tests__/codex-adapter.test.ts +350 -0
  114. package/src/gateway/__tests__/dispatcher.test.ts +1159 -0
  115. package/src/gateway/__tests__/gateway-add-channel.test.ts +180 -0
  116. package/src/gateway/__tests__/gateway-managed-routes.test.ts +181 -0
  117. package/src/gateway/__tests__/gateway.test.ts +222 -0
  118. package/src/gateway/__tests__/router.test.ts +247 -0
  119. package/src/gateway/__tests__/sanitize.test.ts +193 -0
  120. package/src/gateway/__tests__/session-store.test.ts +235 -0
  121. package/src/gateway/channel-manager.ts +349 -0
  122. package/src/gateway/channels/botcord.ts +605 -0
  123. package/src/gateway/channels/index.ts +6 -0
  124. package/src/gateway/channels/sanitize.ts +68 -0
  125. package/src/gateway/dispatcher.ts +554 -0
  126. package/src/gateway/gateway.ts +211 -0
  127. package/src/gateway/index.ts +29 -0
  128. package/src/gateway/log.ts +30 -0
  129. package/src/gateway/router.ts +60 -0
  130. package/src/gateway/runtimes/claude-code.ts +180 -0
  131. package/src/gateway/runtimes/codex.ts +312 -0
  132. package/src/gateway/runtimes/gemini.ts +43 -0
  133. package/src/gateway/runtimes/ndjson-stream.ts +225 -0
  134. package/src/gateway/runtimes/probe.ts +73 -0
  135. package/src/gateway/runtimes/registry.ts +143 -0
  136. package/src/gateway/session-store.ts +157 -0
  137. package/src/gateway/types.ts +325 -0
  138. package/src/index.ts +961 -0
  139. package/src/log.ts +47 -0
  140. package/src/provision.ts +879 -0
  141. package/src/room-context-fetcher.ts +124 -0
  142. package/src/room-context.ts +167 -0
  143. package/src/sender-classify.ts +46 -0
  144. package/src/snapshot-writer.ts +103 -0
  145. package/src/status-render.ts +132 -0
  146. package/src/system-context.ts +162 -0
  147. package/src/turn-text.ts +93 -0
  148. package/src/user-auth.ts +295 -0
  149. package/src/working-memory.ts +352 -0
@@ -0,0 +1,265 @@
1
+ import type { GatewayLogger } from "./log.js";
2
+ /** Set of predicates matched against a normalized inbound message to pick a route. */
3
+ export interface RouteMatch {
4
+ channel?: string;
5
+ accountId?: string;
6
+ conversationId?: string;
7
+ conversationPrefix?: string;
8
+ conversationKind?: "direct" | "group";
9
+ senderId?: string;
10
+ mentioned?: boolean;
11
+ }
12
+ /** Concurrency model for turns sharing the same queue key. */
13
+ export type QueueMode = "serial" | "cancel-previous";
14
+ /** Source-based trust tier used by runtimes to pick default permission flags. */
15
+ export type TrustLevel = "owner" | "trusted" | "public";
16
+ /** Declarative route entry selecting the runtime and execution flags for matched messages. */
17
+ export interface GatewayRoute {
18
+ match?: RouteMatch;
19
+ runtime: string;
20
+ cwd: string;
21
+ extraArgs?: string[];
22
+ queueMode?: QueueMode;
23
+ trustLevel?: TrustLevel;
24
+ }
25
+ /**
26
+ * Per-channel configuration entry. Channel-specific extras (e.g. BotCord
27
+ * `agentId`) are accepted via the index signature so adapters can read them
28
+ * without introducing a tagged-union everywhere.
29
+ */
30
+ export interface GatewayChannelConfig {
31
+ id: string;
32
+ type: string;
33
+ accountId: string;
34
+ [key: string]: unknown;
35
+ }
36
+ /** Root gateway configuration document loaded from disk or assembled in memory. */
37
+ export interface GatewayConfig {
38
+ channels: GatewayChannelConfig[];
39
+ defaultRoute: GatewayRoute;
40
+ routes?: GatewayRoute[];
41
+ /**
42
+ * Daemon-synthesized per-agent routes. Snapshot/debug-only surface —
43
+ * `resolveRoute` reads the live map on the Gateway, not this array.
44
+ * Matched after `routes[]` and before `defaultRoute`.
45
+ */
46
+ managedRoutes?: GatewayRoute[];
47
+ streamBlocks?: boolean;
48
+ }
49
+ /** Normalized inbound message produced by a channel adapter for the dispatcher. */
50
+ export interface GatewayInboundMessage {
51
+ id: string;
52
+ /** Channel adapter id (`ChannelAdapter.id`), not channel type. */
53
+ channel: string;
54
+ accountId: string;
55
+ conversation: {
56
+ id: string;
57
+ kind: "direct" | "group";
58
+ title?: string;
59
+ threadId?: string | null;
60
+ };
61
+ sender: {
62
+ id: string;
63
+ name?: string;
64
+ kind: "user" | "agent" | "system";
65
+ };
66
+ text?: string;
67
+ raw: unknown;
68
+ replyTo?: string | null;
69
+ mentioned?: boolean;
70
+ receivedAt: number;
71
+ trace?: {
72
+ id: string;
73
+ streamable?: boolean;
74
+ };
75
+ }
76
+ /** Inbound envelope wrapping a normalized message with optional upstream ack callbacks. */
77
+ export interface GatewayInboundEnvelope {
78
+ message: GatewayInboundMessage;
79
+ ack?: {
80
+ accept(): Promise<void>;
81
+ reject?(reason: string): Promise<void>;
82
+ };
83
+ }
84
+ /**
85
+ * Channel-agnostic hook that produces a system-context string for a turn.
86
+ * Called before every `runtime.run(...)`; returned value is passed through
87
+ * as `RuntimeRunOptions.systemContext`. Runtimes surface it via
88
+ * `--append-system-prompt` (Claude Code) or an equivalent prefix.
89
+ *
90
+ * Returning `undefined` or an empty string means "no context for this turn".
91
+ * Builders must be resilient — if this throws, the dispatcher logs a warning
92
+ * and continues the turn without systemContext rather than dropping the turn.
93
+ */
94
+ export type SystemContextBuilder = (message: GatewayInboundMessage) => Promise<string | undefined> | string | undefined;
95
+ /**
96
+ * Optional side-effect hook invoked right after the dispatcher acks an
97
+ * envelope, before the turn executes. Intended for bookkeeping such as
98
+ * activity tracking; errors are caught and logged so they do not break the
99
+ * turn. Kept synchronous-or-async to match `SystemContextBuilder` ergonomics.
100
+ */
101
+ export type InboundObserver = (message: GatewayInboundMessage) => Promise<void> | void;
102
+ /**
103
+ * Channel-agnostic hook that composes the user-turn text passed to the
104
+ * runtime. When omitted, the dispatcher passes `message.text.trim()` through
105
+ * as-is. Builders can wrap the content with sender metadata, room headers,
106
+ * reply hints, etc. — anything that should land in the session transcript.
107
+ *
108
+ * Must be synchronous + cheap (runs on the turn's critical path). Throws are
109
+ * caught by the dispatcher and the raw trimmed text is used as a fallback so
110
+ * a buggy composer never drops turns.
111
+ */
112
+ export type UserTurnBuilder = (message: GatewayInboundMessage) => string;
113
+ /** Outbound reply payload passed to `ChannelAdapter.send()`. */
114
+ export interface GatewayOutboundMessage {
115
+ channel: string;
116
+ accountId: string;
117
+ conversationId: string;
118
+ threadId?: string | null;
119
+ text: string;
120
+ replyTo?: string | null;
121
+ traceId?: string | null;
122
+ }
123
+ /** Per-channel status snapshot exposed for `status`/`doctor` style output. */
124
+ export interface ChannelStatusSnapshot {
125
+ channel: string;
126
+ accountId: string;
127
+ running: boolean;
128
+ connected?: boolean;
129
+ restartPending?: boolean;
130
+ reconnectAttempts?: number;
131
+ lastStartAt?: number;
132
+ lastStopAt?: number;
133
+ lastError?: string | null;
134
+ }
135
+ /** Per-turn status snapshot describing a currently-executing runtime invocation. */
136
+ export interface TurnStatusSnapshot {
137
+ key: string;
138
+ channel: string;
139
+ accountId: string;
140
+ conversationId: string;
141
+ runtime: string;
142
+ cwd: string;
143
+ startedAt: number;
144
+ }
145
+ /** Aggregate gateway state combining channel and turn snapshots. */
146
+ export interface GatewayRuntimeSnapshot {
147
+ channels: Record<string, ChannelStatusSnapshot>;
148
+ turns: Record<string, TurnStatusSnapshot>;
149
+ }
150
+ /** Context passed to `ChannelAdapter.start()` for its lifetime. */
151
+ export interface ChannelStartContext {
152
+ config: GatewayConfig;
153
+ accountId: string;
154
+ abortSignal: AbortSignal;
155
+ log: GatewayLogger;
156
+ emit: (event: GatewayInboundEnvelope) => Promise<void>;
157
+ setStatus: (patch: Partial<ChannelStatusSnapshot>) => void;
158
+ }
159
+ /** Context passed to `ChannelAdapter.stop()` when the manager is tearing the channel down. */
160
+ export interface ChannelStopContext {
161
+ reason?: string;
162
+ }
163
+ /** Context passed to `ChannelAdapter.send()` when delivering a reply. */
164
+ export interface ChannelSendContext {
165
+ message: GatewayOutboundMessage;
166
+ log: GatewayLogger;
167
+ }
168
+ /** Result returned by `ChannelAdapter.send()` — the upstream message id if known. */
169
+ export interface ChannelSendResult {
170
+ providerMessageId?: string | null;
171
+ }
172
+ /** Context passed to `ChannelAdapter.streamBlock()` for progressive output forwarding. */
173
+ export interface ChannelStreamBlockContext {
174
+ traceId: string;
175
+ accountId: string;
176
+ conversationId: string;
177
+ block: unknown;
178
+ log: GatewayLogger;
179
+ }
180
+ /** Upstream messaging surface such as BotCord, Telegram, or WeChat. */
181
+ export interface ChannelAdapter {
182
+ readonly id: string;
183
+ readonly type: string;
184
+ start(ctx: ChannelStartContext): Promise<unknown>;
185
+ stop?(ctx: ChannelStopContext): Promise<void>;
186
+ send(ctx: ChannelSendContext): Promise<ChannelSendResult>;
187
+ status?(): ChannelStatusSnapshot;
188
+ streamBlock?(ctx: ChannelStreamBlockContext): Promise<void>;
189
+ }
190
+ /** One parsed block from a runtime's streaming output, forwarded via `onBlock`. */
191
+ export interface StreamBlock {
192
+ /** Raw JSON object as emitted by the underlying CLI (e.g. claude-code stream-json). */
193
+ raw: unknown;
194
+ /** Normalized kind, used by channels to decide whether to forward progressive output. */
195
+ kind: "assistant_text" | "tool_use" | "tool_result" | "system" | "other";
196
+ /** 1-based sequence number within this turn. */
197
+ seq: number;
198
+ }
199
+ /** Options passed to a runtime adapter for a single turn. */
200
+ export interface RuntimeRunOptions {
201
+ text: string;
202
+ /** Runtime-native session id for resume; null/empty for a new session. */
203
+ sessionId: string | null;
204
+ cwd: string;
205
+ /**
206
+ * Owning agent id (the daemon's `accountId` for this route). Lets adapters
207
+ * resolve per-agent state — e.g. the codex adapter uses it to locate the
208
+ * per-agent `CODEX_HOME` carrying the AGENTS.md that injects systemContext.
209
+ */
210
+ accountId: string;
211
+ signal: AbortSignal;
212
+ extraArgs?: string[];
213
+ trustLevel: TrustLevel;
214
+ /** System-level context injected alongside the user turn (memory, digest, room info). */
215
+ systemContext?: string;
216
+ /** Channel-agnostic bag for dispatch-time data (traceId, channel, conversation, etc.). */
217
+ context?: Record<string, unknown>;
218
+ /** Called for every parsed block while the turn is in progress. */
219
+ onBlock?: (block: StreamBlock) => void;
220
+ }
221
+ /** Result returned by a runtime adapter after a turn completes. */
222
+ export interface RuntimeRunResult {
223
+ /** Final assistant text for this turn (concatenated if streamed). */
224
+ text: string;
225
+ /** New runtime session id to persist so the next turn can resume. */
226
+ newSessionId: string;
227
+ /** Optional cost in USD, if the runtime reports it. */
228
+ costUsd?: number;
229
+ /** Populated when the runtime reported a hard error. */
230
+ error?: string;
231
+ }
232
+ /** Detection result for whether a runtime binary/SDK is usable on this machine. */
233
+ export interface RuntimeProbeResult {
234
+ available: boolean;
235
+ path?: string;
236
+ version?: string;
237
+ }
238
+ /** Downstream agent executor such as Claude Code, Codex, Gemini, or OpenClaw. */
239
+ export interface RuntimeAdapter {
240
+ readonly id: string;
241
+ run(opts: RuntimeRunOptions): Promise<RuntimeRunResult>;
242
+ probe?(): RuntimeProbeResult;
243
+ }
244
+ /** Minimal fields needed to derive a session key for the JSON session store. */
245
+ export interface SessionKeyInput {
246
+ runtime: string;
247
+ channel: string;
248
+ accountId: string;
249
+ conversationKind: "direct" | "group";
250
+ conversationId: string;
251
+ threadId?: string | null;
252
+ }
253
+ /** Persisted runtime-session record keyed by the derived session key. */
254
+ export interface GatewaySessionEntry {
255
+ key: string;
256
+ runtime: string;
257
+ runtimeSessionId: string;
258
+ channel: string;
259
+ accountId: string;
260
+ conversationKind: "direct" | "group";
261
+ conversationId: string;
262
+ threadId?: string | null;
263
+ cwd: string;
264
+ updatedAt: number;
265
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};