reeboot 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.
Files changed (110) hide show
  1. package/README.md +361 -0
  2. package/container/Dockerfile +48 -0
  3. package/container/entrypoint.sh +8 -0
  4. package/dist/agent-runner/index.d.ts +9 -0
  5. package/dist/agent-runner/index.d.ts.map +1 -0
  6. package/dist/agent-runner/index.js +21 -0
  7. package/dist/agent-runner/index.js.map +1 -0
  8. package/dist/agent-runner/interface.d.ts +56 -0
  9. package/dist/agent-runner/interface.d.ts.map +1 -0
  10. package/dist/agent-runner/interface.js +5 -0
  11. package/dist/agent-runner/interface.js.map +1 -0
  12. package/dist/agent-runner/pi-runner.d.ts +41 -0
  13. package/dist/agent-runner/pi-runner.d.ts.map +1 -0
  14. package/dist/agent-runner/pi-runner.js +162 -0
  15. package/dist/agent-runner/pi-runner.js.map +1 -0
  16. package/dist/channels/interface.d.ts +63 -0
  17. package/dist/channels/interface.d.ts.map +1 -0
  18. package/dist/channels/interface.js +33 -0
  19. package/dist/channels/interface.js.map +1 -0
  20. package/dist/channels/registry.d.ts +30 -0
  21. package/dist/channels/registry.d.ts.map +1 -0
  22. package/dist/channels/registry.js +71 -0
  23. package/dist/channels/registry.js.map +1 -0
  24. package/dist/channels/signal.d.ts +51 -0
  25. package/dist/channels/signal.d.ts.map +1 -0
  26. package/dist/channels/signal.js +263 -0
  27. package/dist/channels/signal.js.map +1 -0
  28. package/dist/channels/web.d.ts +35 -0
  29. package/dist/channels/web.d.ts.map +1 -0
  30. package/dist/channels/web.js +65 -0
  31. package/dist/channels/web.js.map +1 -0
  32. package/dist/channels/whatsapp.d.ts +25 -0
  33. package/dist/channels/whatsapp.d.ts.map +1 -0
  34. package/dist/channels/whatsapp.js +150 -0
  35. package/dist/channels/whatsapp.js.map +1 -0
  36. package/dist/config.d.ts +366 -0
  37. package/dist/config.d.ts.map +1 -0
  38. package/dist/config.js +140 -0
  39. package/dist/config.js.map +1 -0
  40. package/dist/context.d.ts +69 -0
  41. package/dist/context.d.ts.map +1 -0
  42. package/dist/context.js +166 -0
  43. package/dist/context.js.map +1 -0
  44. package/dist/credential-proxy.d.ts +25 -0
  45. package/dist/credential-proxy.d.ts.map +1 -0
  46. package/dist/credential-proxy.js +96 -0
  47. package/dist/credential-proxy.js.map +1 -0
  48. package/dist/daemon.d.ts +25 -0
  49. package/dist/daemon.d.ts.map +1 -0
  50. package/dist/daemon.js +138 -0
  51. package/dist/daemon.js.map +1 -0
  52. package/dist/db/index.d.ts +23 -0
  53. package/dist/db/index.d.ts.map +1 -0
  54. package/dist/db/index.js +113 -0
  55. package/dist/db/index.js.map +1 -0
  56. package/dist/db/schema.d.ts +408 -0
  57. package/dist/db/schema.d.ts.map +1 -0
  58. package/dist/db/schema.js +55 -0
  59. package/dist/db/schema.js.map +1 -0
  60. package/dist/doctor.d.ts +23 -0
  61. package/dist/doctor.d.ts.map +1 -0
  62. package/dist/doctor.js +217 -0
  63. package/dist/doctor.js.map +1 -0
  64. package/dist/extensions/loader.d.ts +19 -0
  65. package/dist/extensions/loader.d.ts.map +1 -0
  66. package/dist/extensions/loader.js +124 -0
  67. package/dist/extensions/loader.js.map +1 -0
  68. package/dist/index.d.ts +3 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +561 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/orchestrator.d.ts +60 -0
  73. package/dist/orchestrator.d.ts.map +1 -0
  74. package/dist/orchestrator.js +313 -0
  75. package/dist/orchestrator.js.map +1 -0
  76. package/dist/packages.d.ts +21 -0
  77. package/dist/packages.d.ts.map +1 -0
  78. package/dist/packages.js +116 -0
  79. package/dist/packages.js.map +1 -0
  80. package/dist/scheduler-registry.d.ts +8 -0
  81. package/dist/scheduler-registry.d.ts.map +1 -0
  82. package/dist/scheduler-registry.js +14 -0
  83. package/dist/scheduler-registry.js.map +1 -0
  84. package/dist/scheduler.d.ts +60 -0
  85. package/dist/scheduler.d.ts.map +1 -0
  86. package/dist/scheduler.js +143 -0
  87. package/dist/scheduler.js.map +1 -0
  88. package/dist/server.d.ts +18 -0
  89. package/dist/server.d.ts.map +1 -0
  90. package/dist/server.js +489 -0
  91. package/dist/server.js.map +1 -0
  92. package/dist/setup-wizard.d.ts +12 -0
  93. package/dist/setup-wizard.d.ts.map +1 -0
  94. package/dist/setup-wizard.js +163 -0
  95. package/dist/setup-wizard.js.map +1 -0
  96. package/extensions/confirm-destructive.ts +59 -0
  97. package/extensions/custom-compaction.ts +114 -0
  98. package/extensions/protected-paths.ts +30 -0
  99. package/extensions/sandbox/index.ts +317 -0
  100. package/extensions/sandbox/package-lock.json +92 -0
  101. package/extensions/sandbox/package.json +19 -0
  102. package/extensions/scheduler-tool.ts +65 -0
  103. package/extensions/session-name.ts +27 -0
  104. package/extensions/token-meter.ts +55 -0
  105. package/package.json +68 -0
  106. package/skills/send-message/SKILL.md +27 -0
  107. package/skills/web-search/SKILL.md +32 -0
  108. package/templates/global-agents.md +23 -0
  109. package/templates/main-agents.md +28 -0
  110. package/webchat/index.html +421 -0
@@ -0,0 +1,162 @@
1
+ /**
2
+ * PiAgentRunner — wraps the pi SDK AgentSession.
3
+ *
4
+ * Pi SDK event mapping (verified against @mariozechner/pi-agent-core types.d.ts):
5
+ *
6
+ * pi event → RunnerEvent
7
+ * ─────────────────────────────────────────────────────────────────────
8
+ * message_update → text_delta
9
+ * .assistantMessageEvent.type === "text_delta"
10
+ * .assistantMessageEvent.delta (the text string)
11
+ *
12
+ * tool_execution_start → tool_call_start
13
+ * .toolCallId, .toolName, .args
14
+ *
15
+ * tool_execution_end → tool_call_end
16
+ * .toolCallId, .toolName, .result, .isError
17
+ *
18
+ * agent_end → message_end
19
+ * (usage is retrieved from session stats — pi does not put it on agent_end directly)
20
+ *
21
+ * All other pi events are silently ignored.
22
+ *
23
+ * agentDir: ~/.reeboot/ (global extensions/skills)
24
+ * cwd: context.workspacePath (project-local discovery)
25
+ */
26
+ import { nanoid } from 'nanoid';
27
+ export class PiAgentRunner {
28
+ context;
29
+ loader;
30
+ abortController = null;
31
+ disposed = false;
32
+ // Lazily created on first prompt
33
+ _session = null;
34
+ constructor(context, loader) {
35
+ this.context = context;
36
+ this.loader = loader;
37
+ }
38
+ // ── prompt ─────────────────────────────────────────────────────────────────
39
+ async prompt(content, onEvent) {
40
+ if (this.disposed) {
41
+ throw new Error('PiAgentRunner has been disposed');
42
+ }
43
+ const session = await this._getOrCreateSession();
44
+ const runId = nanoid();
45
+ this.abortController = new AbortController();
46
+ const { signal } = this.abortController;
47
+ return new Promise((resolve, reject) => {
48
+ // Subscribe before prompting so we don't miss early events
49
+ const unsubscribe = session.subscribe((event) => {
50
+ if (signal.aborted)
51
+ return;
52
+ if (event.type === 'message_update') {
53
+ const ae = event.assistantMessageEvent;
54
+ if (ae.type === 'text_delta') {
55
+ onEvent({ type: 'text_delta', delta: ae.delta });
56
+ }
57
+ }
58
+ else if (event.type === 'tool_execution_start') {
59
+ onEvent({
60
+ type: 'tool_call_start',
61
+ toolCallId: event.toolCallId,
62
+ toolName: event.toolName,
63
+ args: event.args,
64
+ });
65
+ }
66
+ else if (event.type === 'tool_execution_end') {
67
+ onEvent({
68
+ type: 'tool_call_end',
69
+ toolCallId: event.toolCallId,
70
+ toolName: event.toolName,
71
+ result: event.result,
72
+ isError: event.isError,
73
+ });
74
+ }
75
+ else if (event.type === 'agent_end') {
76
+ // Extract usage from the last assistant message if available
77
+ let inputTokens = 0;
78
+ let outputTokens = 0;
79
+ const messages = event.messages;
80
+ // Look for the last assistant message to get token info
81
+ for (let i = messages.length - 1; i >= 0; i--) {
82
+ const m = messages[i];
83
+ if (m.role === 'assistant' && m.usage) {
84
+ inputTokens = m.usage.inputTokens ?? 0;
85
+ outputTokens = m.usage.outputTokens ?? 0;
86
+ break;
87
+ }
88
+ }
89
+ onEvent({
90
+ type: 'message_end',
91
+ runId,
92
+ usage: { input: inputTokens, output: outputTokens },
93
+ });
94
+ unsubscribe();
95
+ this.abortController = null;
96
+ resolve();
97
+ }
98
+ });
99
+ // Abort handling
100
+ signal.addEventListener('abort', () => {
101
+ unsubscribe();
102
+ this.abortController = null;
103
+ reject(new DOMException('Prompt aborted', 'AbortError'));
104
+ }, { once: true });
105
+ // Fire the prompt
106
+ session.prompt(content).catch((err) => {
107
+ unsubscribe();
108
+ this.abortController = null;
109
+ if (signal.aborted) {
110
+ reject(new DOMException('Prompt aborted', 'AbortError'));
111
+ }
112
+ else {
113
+ onEvent({ type: 'error', message: String(err?.message ?? err) });
114
+ reject(err);
115
+ }
116
+ });
117
+ });
118
+ }
119
+ // ── abort ──────────────────────────────────────────────────────────────────
120
+ abort() {
121
+ if (this.abortController) {
122
+ this.abortController.abort();
123
+ this.abortController = null;
124
+ }
125
+ // Also abort the underlying session if it exists
126
+ if (this._session) {
127
+ try {
128
+ this._session.abort();
129
+ }
130
+ catch {
131
+ // ignore
132
+ }
133
+ }
134
+ }
135
+ // ── dispose ────────────────────────────────────────────────────────────────
136
+ async dispose() {
137
+ if (this.disposed)
138
+ return;
139
+ this.disposed = true;
140
+ this.abort();
141
+ // No dispose() on AgentSession in pi SDK — it persists state on its own
142
+ this._session = null;
143
+ }
144
+ // ── reload ─────────────────────────────────────────────────────────────────
145
+ async reload() {
146
+ await this.loader.reload();
147
+ }
148
+ // ── internal ───────────────────────────────────────────────────────────────
149
+ async _getOrCreateSession() {
150
+ if (this._session)
151
+ return this._session;
152
+ const { createAgentSession, SessionManager } = await import('@mariozechner/pi-coding-agent');
153
+ const { session } = await createAgentSession({
154
+ cwd: this.context.workspacePath,
155
+ resourceLoader: this.loader,
156
+ sessionManager: SessionManager.inMemory(),
157
+ });
158
+ this._session = session;
159
+ return session;
160
+ }
161
+ }
162
+ //# sourceMappingURL=pi-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-runner.js","sourceRoot":"","sources":["../../src/agent-runner/pi-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Channel Adapter Interface
3
+ *
4
+ * Defines the ChannelAdapter, MessageBus, and related types that all channel
5
+ * implementations must satisfy. Exported from `reeboot/channels`.
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ export declare const CHANNEL_STATUS_VALUES: readonly ["connected", "disconnected", "error", "initializing"];
9
+ export type ChannelStatus = typeof CHANNEL_STATUS_VALUES[number];
10
+ export interface MessageContent {
11
+ type: 'text' | 'image';
12
+ text?: string;
13
+ /** base64-encoded image data for type === 'image' */
14
+ imageData?: string;
15
+ mimeType?: string;
16
+ }
17
+ export interface IncomingMessage {
18
+ /** Which channel type originated this message, e.g. "whatsapp", "web" */
19
+ channelType: string;
20
+ /** Peer identifier — phone number JID for WhatsApp, socket ID for web, etc. */
21
+ peerId: string;
22
+ /** Plain text content extracted from the message */
23
+ content: string;
24
+ /** Unix timestamp (ms) when the message was received */
25
+ timestamp: number;
26
+ /** Provider-specific original message object (Baileys message, WS message, etc.) */
27
+ raw: unknown;
28
+ }
29
+ /**
30
+ * Helper to construct an IncomingMessage with defaults.
31
+ */
32
+ export declare function createIncomingMessage(fields: Omit<IncomingMessage, 'timestamp'> & {
33
+ timestamp?: number;
34
+ }): IncomingMessage;
35
+ /**
36
+ * EventEmitter-based message bus.
37
+ * Channels emit 'message' events; the orchestrator subscribes.
38
+ */
39
+ export declare class MessageBus extends EventEmitter {
40
+ publish(message: IncomingMessage): void;
41
+ onMessage(handler: (message: IncomingMessage) => void): () => void;
42
+ }
43
+ export interface ChannelConfig {
44
+ enabled: boolean;
45
+ /** Optional path to a custom adapter .ts file */
46
+ adapter?: string;
47
+ [key: string]: unknown;
48
+ }
49
+ export interface ChannelAdapter {
50
+ /** Initialize the adapter: register with bus, set up internals */
51
+ init(config: ChannelConfig, bus: MessageBus): Promise<void>;
52
+ /** Open the channel connection */
53
+ start(): Promise<void>;
54
+ /** Close the channel connection gracefully */
55
+ stop(): Promise<void>;
56
+ /** Send a message to a peer */
57
+ send(peerId: string, content: MessageContent): Promise<void>;
58
+ /** Current connection status */
59
+ status(): ChannelStatus;
60
+ /** ISO timestamp when status last became 'connected', or null */
61
+ connectedAt(): string | null;
62
+ }
63
+ //# sourceMappingURL=interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/channels/interface.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,eAAO,MAAM,qBAAqB,iEAAkE,CAAC;AACrG,MAAM,MAAM,aAAa,GAAG,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAIjE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,GAAG,EAAE,OAAO,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAClE,eAAe,CAKjB;AAID;;;GAGG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAIvC,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;CAInE;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,kCAAkC;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,8CAA8C;IAC9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,+BAA+B;IAC/B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,gCAAgC;IAChC,MAAM,IAAI,aAAa,CAAC;IACxB,iEAAiE;IACjE,WAAW,IAAI,MAAM,GAAG,IAAI,CAAC;CAC9B"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Channel Adapter Interface
3
+ *
4
+ * Defines the ChannelAdapter, MessageBus, and related types that all channel
5
+ * implementations must satisfy. Exported from `reeboot/channels`.
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ // ─── ChannelStatus ────────────────────────────────────────────────────────────
9
+ export const CHANNEL_STATUS_VALUES = ['connected', 'disconnected', 'error', 'initializing'];
10
+ /**
11
+ * Helper to construct an IncomingMessage with defaults.
12
+ */
13
+ export function createIncomingMessage(fields) {
14
+ return {
15
+ timestamp: Date.now(),
16
+ ...fields,
17
+ };
18
+ }
19
+ // ─── MessageBus ───────────────────────────────────────────────────────────────
20
+ /**
21
+ * EventEmitter-based message bus.
22
+ * Channels emit 'message' events; the orchestrator subscribes.
23
+ */
24
+ export class MessageBus extends EventEmitter {
25
+ publish(message) {
26
+ this.emit('message', message);
27
+ }
28
+ onMessage(handler) {
29
+ this.on('message', handler);
30
+ return () => this.off('message', handler);
31
+ }
32
+ }
33
+ //# sourceMappingURL=interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/channels/interface.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,iFAAiF;AAEjF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,CAAU,CAAC;AA4BrG;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAmE;IAEnE,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,GAAG,MAAM;KACV,CAAC;AACJ,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,OAAO,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,OAAwB;QAC9B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,SAAS,CAAC,OAA2C;QACnD,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Channel Registry
3
+ *
4
+ * Self-registering adapter registry. Built-in adapters call registerChannel()
5
+ * at module import time. Custom adapters are loaded via dynamic import from
6
+ * config.channels.<type>.adapter paths.
7
+ */
8
+ import type { ChannelAdapter, ChannelConfig, MessageBus } from './interface.js';
9
+ type AdapterFactory = () => ChannelAdapter;
10
+ export declare class ChannelRegistry {
11
+ private _factories;
12
+ register(type: string, factory: AdapterFactory): void;
13
+ get(type: string): AdapterFactory | undefined;
14
+ /**
15
+ * Initialise channels from config.
16
+ * - All known channel types are instantiated and added to the returned map
17
+ * (so they always appear in GET /api/channels).
18
+ * - Only enabled channels are started (init + start called).
19
+ * - Custom adapter paths are loaded via dynamic import.
20
+ * - Load/start errors are caught per-adapter; other channels continue.
21
+ * Returns a map of ALL adapters (started or not).
22
+ */
23
+ initChannels(config: {
24
+ channels: Record<string, ChannelConfig>;
25
+ }, bus: MessageBus): Promise<Map<string, ChannelAdapter>>;
26
+ }
27
+ export declare const globalRegistry: ChannelRegistry;
28
+ export declare function registerChannel(type: string, factory: AdapterFactory): void;
29
+ export {};
30
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/channels/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEhF,KAAK,cAAc,GAAG,MAAM,cAAc,CAAC;AAI3C,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAqC;IAEvD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAIrD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI7C;;;;;;;;OAQG;IACG,YAAY,CAChB,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;KAAE,EACnD,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CA2CxC;AAID,eAAO,MAAM,cAAc,iBAAwB,CAAC;AAEpD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAE3E"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Channel Registry
3
+ *
4
+ * Self-registering adapter registry. Built-in adapters call registerChannel()
5
+ * at module import time. Custom adapters are loaded via dynamic import from
6
+ * config.channels.<type>.adapter paths.
7
+ */
8
+ // ─── ChannelRegistry ─────────────────────────────────────────────────────────
9
+ export class ChannelRegistry {
10
+ _factories = new Map();
11
+ register(type, factory) {
12
+ this._factories.set(type, factory);
13
+ }
14
+ get(type) {
15
+ return this._factories.get(type);
16
+ }
17
+ /**
18
+ * Initialise channels from config.
19
+ * - All known channel types are instantiated and added to the returned map
20
+ * (so they always appear in GET /api/channels).
21
+ * - Only enabled channels are started (init + start called).
22
+ * - Custom adapter paths are loaded via dynamic import.
23
+ * - Load/start errors are caught per-adapter; other channels continue.
24
+ * Returns a map of ALL adapters (started or not).
25
+ */
26
+ async initChannels(config, bus) {
27
+ const all = new Map();
28
+ for (const [type, channelCfg] of Object.entries(config.channels)) {
29
+ try {
30
+ let factory = this._factories.get(type);
31
+ // Try loading a custom adapter from config path
32
+ if (!factory && channelCfg.adapter) {
33
+ try {
34
+ const mod = await import(channelCfg.adapter);
35
+ if (typeof mod.default === 'function') {
36
+ factory = mod.default;
37
+ this._factories.set(type, factory);
38
+ }
39
+ else {
40
+ throw new Error(`Custom adapter at ${channelCfg.adapter} has no default export factory`);
41
+ }
42
+ }
43
+ catch (err) {
44
+ console.error(`[ChannelRegistry] Failed to load custom adapter for "${type}": ${err}`);
45
+ continue;
46
+ }
47
+ }
48
+ if (!factory) {
49
+ console.warn(`[ChannelRegistry] No adapter registered for channel type "${type}" — skipping`);
50
+ continue;
51
+ }
52
+ const adapter = factory();
53
+ if (channelCfg.enabled) {
54
+ await adapter.init(channelCfg, bus);
55
+ await adapter.start();
56
+ }
57
+ all.set(type, adapter);
58
+ }
59
+ catch (err) {
60
+ console.error(`[ChannelRegistry] Failed to initialise channel "${type}": ${err}`);
61
+ }
62
+ }
63
+ return all;
64
+ }
65
+ }
66
+ // ─── Global singleton registry ────────────────────────────────────────────────
67
+ export const globalRegistry = new ChannelRegistry();
68
+ export function registerChannel(type, factory) {
69
+ globalRegistry.register(type, factory);
70
+ }
71
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/channels/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,gFAAgF;AAEhF,MAAM,OAAO,eAAe;IAClB,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEvD,QAAQ,CAAC,IAAY,EAAE,OAAuB;QAC5C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,YAAY,CAChB,MAAmD,EACnD,GAAe;QAEf,MAAM,GAAG,GAAG,IAAI,GAAG,EAA0B,CAAC;QAE9C,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC;gBACH,IAAI,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAExC,gDAAgD;gBAChD,IAAI,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;oBACnC,IAAI,CAAC;wBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;wBAC7C,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;4BACtC,OAAO,GAAG,GAAG,CAAC,OAAyB,CAAC;4BACxC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;wBACrC,CAAC;6BAAM,CAAC;4BACN,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,CAAC,OAAO,gCAAgC,CAAC,CAAC;wBAC3F,CAAC;oBACH,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,OAAO,CAAC,KAAK,CAAC,wDAAwD,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;wBACvF,SAAS;oBACX,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,CAAC,IAAI,CAAC,6DAA6D,IAAI,cAAc,CAAC,CAAC;oBAC9F,SAAS;gBACX,CAAC;gBAED,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC;gBAE1B,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;oBACvB,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;oBACpC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBACxB,CAAC;gBAED,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACzB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,mDAAmD,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,iFAAiF;AAEjF,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,eAAe,EAAE,CAAC;AAEpD,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAuB;IACnE,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Signal channel adapter
3
+ *
4
+ * Uses bbernhard/signal-cli-rest-api Docker sidecar.
5
+ *
6
+ * Receive strategy depends on the API mode reported by /v1/about:
7
+ * - json-rpc mode → WebSocket on ws://host/v1/receive/<number>
8
+ * - normal/native mode → HTTP polling GET /v1/receive/<number>
9
+ *
10
+ * Sends via POST /v2/send (same for all modes).
11
+ */
12
+ import type { ChannelAdapter, ChannelConfig, MessageBus, MessageContent, ChannelStatus } from './interface.js';
13
+ export interface SignalAdapterOptions {
14
+ phoneNumber?: string;
15
+ apiPort?: number;
16
+ pollInterval?: number;
17
+ }
18
+ /**
19
+ * Check if a signal-cli-rest-api Docker container is running.
20
+ * Returns true if found, false otherwise.
21
+ */
22
+ export declare function detectSignalContainer(): boolean;
23
+ export declare class SignalAdapter implements ChannelAdapter {
24
+ private _status;
25
+ private _connectedAt;
26
+ private _bus;
27
+ private _pollTimer;
28
+ private _ws;
29
+ private _wsReconnectTimer;
30
+ private _wsStopped;
31
+ readonly _phoneNumber: string;
32
+ readonly _apiPort: number;
33
+ readonly _pollInterval: number;
34
+ constructor(opts?: SignalAdapterOptions);
35
+ private get _baseUrl();
36
+ private get _wsBaseUrl();
37
+ init(config: ChannelConfig, bus: MessageBus): Promise<void>;
38
+ private _setPhoneNumber;
39
+ private _setApiPort;
40
+ start(): Promise<void>;
41
+ private _connectWebSocket;
42
+ private _startPolling;
43
+ private _poll;
44
+ private _handleIncomingMessage;
45
+ stop(): Promise<void>;
46
+ send(peerId: string, content: MessageContent): Promise<void>;
47
+ private _sendChunk;
48
+ status(): ChannelStatus;
49
+ connectedAt(): string | null;
50
+ }
51
+ //# sourceMappingURL=signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/channels/signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAY/G,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAU/C;AAgBD,qBAAa,aAAc,YAAW,cAAc;IAClD,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,IAAI,CAA2B;IAGvC,OAAO,CAAC,UAAU,CAA+C;IAGjE,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,iBAAiB,CAA8C;IACvE,OAAO,CAAC,UAAU,CAAS;IAE3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,IAAI,GAAE,oBAAyB;IAM3C,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,KAAK,UAAU,GAErB;IAEK,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjE,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,WAAW;IAEb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC5B,OAAO,CAAC,iBAAiB;IAmCzB,OAAO,CAAC,aAAa;YASP,KAAK;IAiBnB,OAAO,CAAC,sBAAsB;IAiCxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBrB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;YAmBpD,UAAU;IAiBxB,MAAM,IAAI,aAAa;IAIvB,WAAW,IAAI,MAAM,GAAG,IAAI;CAG7B"}