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,313 @@
1
+ /**
2
+ * Orchestrator
3
+ *
4
+ * Subscribes to the MessageBus, applies routing rules, dispatches incoming
5
+ * messages to the correct context's AgentRunner, handles in-chat commands,
6
+ * manages per-context inactivity timers, and queues messages when a context
7
+ * is busy.
8
+ *
9
+ * Routing priority: peer match > channel match > default
10
+ * Queue depth: max 5 messages per context; overflow gets "queue full" reply.
11
+ */
12
+ import { statfsSync } from 'fs';
13
+ import { homedir } from 'os';
14
+ import { join } from 'path';
15
+ // ─── Constants ────────────────────────────────────────────────────────────────
16
+ const MAX_QUEUE_DEPTH = 5;
17
+ const DEFAULT_INACTIVITY_MS = 14_400_000; // 4 hours
18
+ const DEFAULT_TURN_TIMEOUT_MS = 300_000; // 5 min
19
+ const DEFAULT_RATE_LIMIT_RETRIES = 3;
20
+ const DISK_SPACE_MIN_BYTES = 100 * 1024 * 1024; // 100MB
21
+ const BUSY_REPLY = "I'm still working on your last request. Please wait.";
22
+ const QUEUE_FULL_REPLY = "Queue full. Please wait for the current messages to be processed.";
23
+ // ─── Disk space check ─────────────────────────────────────────────────────────
24
+ function checkDiskSpace() {
25
+ try {
26
+ const reebotDir = join(homedir(), '.reeboot');
27
+ const stats = statfsSync(reebotDir);
28
+ const freeBytes = stats.bfree * stats.bsize;
29
+ if (freeBytes < DISK_SPACE_MIN_BYTES) {
30
+ const freeMB = Math.floor(freeBytes / (1024 * 1024));
31
+ return {
32
+ ok: false,
33
+ message: `Disk space critically low (${freeMB}MB free). Cannot start new agent turn. Free up space in ~/.reeboot/`,
34
+ };
35
+ }
36
+ return { ok: true };
37
+ }
38
+ catch {
39
+ // Can't check — allow turn to proceed
40
+ return { ok: true };
41
+ }
42
+ }
43
+ // ─── Orchestrator ─────────────────────────────────────────────────────────────
44
+ export class Orchestrator {
45
+ _config;
46
+ _bus;
47
+ _adapters;
48
+ _runners;
49
+ _contextState = new Map();
50
+ _unsubscribe = null;
51
+ constructor(config, bus, adapters, runners) {
52
+ this._config = config;
53
+ this._bus = bus;
54
+ this._adapters = adapters;
55
+ this._runners = runners;
56
+ }
57
+ start() {
58
+ this._unsubscribe = this._bus.onMessage((msg) => this._handleMessage(msg));
59
+ }
60
+ stop() {
61
+ if (this._unsubscribe) {
62
+ this._unsubscribe();
63
+ this._unsubscribe = null;
64
+ }
65
+ for (const state of this._contextState.values()) {
66
+ if (state.inactivityTimer)
67
+ clearTimeout(state.inactivityTimer);
68
+ }
69
+ }
70
+ // ── Routing ───────────────────────────────────────────────────────────────
71
+ _resolveContext(msg) {
72
+ const rules = this._config.routing.rules ?? [];
73
+ // Check per-peer runtime override first
74
+ for (const state of this._contextState.values()) {
75
+ const override = state.peerContextOverride.get(msg.peerId);
76
+ if (override)
77
+ return override;
78
+ }
79
+ // Peer match
80
+ for (const rule of rules) {
81
+ if (rule.peer && rule.peer === msg.peerId)
82
+ return rule.context;
83
+ }
84
+ // Channel match
85
+ for (const rule of rules) {
86
+ if (rule.channel && rule.channel === msg.channelType)
87
+ return rule.context;
88
+ }
89
+ return this._config.routing.default ?? 'main';
90
+ }
91
+ // ── Message handling ──────────────────────────────────────────────────────
92
+ _handleMessage(msg) {
93
+ const contextId = this._resolveContext(msg);
94
+ const state = this._getOrCreateContextState(contextId);
95
+ // Reset inactivity timer
96
+ this._resetInactivityTimer(contextId, state);
97
+ if (state.busy) {
98
+ // Queue or drop
99
+ if (state.queue.length >= MAX_QUEUE_DEPTH) {
100
+ this._reply(msg, QUEUE_FULL_REPLY);
101
+ }
102
+ else {
103
+ state.queue.push(msg);
104
+ this._reply(msg, BUSY_REPLY);
105
+ }
106
+ return;
107
+ }
108
+ this._dispatch(contextId, msg);
109
+ }
110
+ _dispatch(contextId, msg) {
111
+ const state = this._getOrCreateContextState(contextId);
112
+ state.busy = true;
113
+ // Run async without blocking
114
+ this._runTurn(contextId, msg).finally(() => {
115
+ state.busy = false;
116
+ // Process next queued message if any
117
+ if (state.queue.length > 0) {
118
+ const next = state.queue.shift();
119
+ this._dispatch(contextId, next);
120
+ }
121
+ });
122
+ }
123
+ async _runTurn(contextId, msg) {
124
+ // Check for in-chat command
125
+ if (msg.content.startsWith('/')) {
126
+ const handled = await this._handleCommand(contextId, msg);
127
+ if (handled)
128
+ return;
129
+ }
130
+ // Disk space pre-check
131
+ const disk = checkDiskSpace();
132
+ if (!disk.ok) {
133
+ this._reply(msg, disk.message);
134
+ return;
135
+ }
136
+ const runner = this._runners.get(contextId);
137
+ if (!runner) {
138
+ this._reply(msg, `No runner found for context "${contextId}".`);
139
+ return;
140
+ }
141
+ const turnTimeoutMs = this._config.agent?.turnTimeout ?? DEFAULT_TURN_TIMEOUT_MS;
142
+ const maxRetries = this._config.agent?.rateLimitRetries ?? DEFAULT_RATE_LIMIT_RETRIES;
143
+ let responseText = '';
144
+ let retries = 0;
145
+ while (true) {
146
+ responseText = '';
147
+ // Build a promise that races the turn vs. timeout
148
+ let aborted = false;
149
+ const turnPromise = runner.prompt(msg.content, (event) => {
150
+ if (event.type === 'text_delta') {
151
+ responseText += event.delta;
152
+ }
153
+ });
154
+ let timeoutHandle = null;
155
+ const timeoutPromise = new Promise((resolve) => {
156
+ timeoutHandle = setTimeout(() => resolve('timeout'), turnTimeoutMs);
157
+ });
158
+ let result = 'done';
159
+ let turnError = null;
160
+ try {
161
+ const winner = await Promise.race([
162
+ turnPromise.then(() => 'done'),
163
+ timeoutPromise,
164
+ ]);
165
+ if (winner === 'timeout') {
166
+ aborted = true;
167
+ result = 'timeout';
168
+ try {
169
+ runner.abort();
170
+ }
171
+ catch { /* ignore */ }
172
+ }
173
+ }
174
+ catch (err) {
175
+ result = 'error';
176
+ turnError = err;
177
+ }
178
+ finally {
179
+ if (timeoutHandle)
180
+ clearTimeout(timeoutHandle);
181
+ }
182
+ if (result === 'timeout') {
183
+ this._reply(msg, 'Your request timed out. The agent took too long to respond.');
184
+ return;
185
+ }
186
+ if (result === 'error') {
187
+ const err = turnError;
188
+ if (err?.name === 'AbortError')
189
+ return;
190
+ // Check for rate limit (HTTP 429)
191
+ const isRateLimit = err?.status === 429 ||
192
+ (err?.message ?? '').toLowerCase().includes('rate limit');
193
+ if (isRateLimit && retries < maxRetries) {
194
+ retries++;
195
+ // Exponential backoff: base is configurable (default 5s), tests can inject 10ms
196
+ const backoffBase = this._config.agent?._testBackoffMs ?? 5000;
197
+ const delayMs = Math.pow(2, retries) * backoffBase; // 10s, 20s, 40s (or 20ms, 40ms in tests)
198
+ this._reply(msg, `Rate limited — retrying in ${Math.round(delayMs / 1000)}s (attempt ${retries}/${maxRetries})...`);
199
+ await new Promise(r => setTimeout(r, delayMs));
200
+ continue; // retry
201
+ }
202
+ // Non-retryable error
203
+ this._reply(msg, `Error: ${err?.message ?? String(err)}`);
204
+ return;
205
+ }
206
+ // Success
207
+ break;
208
+ }
209
+ if (responseText) {
210
+ this._reply(msg, responseText);
211
+ }
212
+ }
213
+ // ── In-chat commands ──────────────────────────────────────────────────────
214
+ async _handleCommand(contextId, msg) {
215
+ const content = msg.content.trim();
216
+ const parts = content.split(/\s+/);
217
+ const cmd = parts[0].toLowerCase();
218
+ if (cmd === '/new') {
219
+ await this.handleNew(contextId, msg);
220
+ return true;
221
+ }
222
+ if (cmd === '/context' && parts[1]) {
223
+ await this.handleContext(contextId, msg, parts[1]);
224
+ return true;
225
+ }
226
+ if (cmd === '/contexts') {
227
+ await this.handleContexts(contextId, msg);
228
+ return true;
229
+ }
230
+ if (cmd === '/status') {
231
+ await this.handleStatus(contextId, msg);
232
+ return true;
233
+ }
234
+ if (cmd === '/compact') {
235
+ await this.handleCompact(contextId, msg);
236
+ return true;
237
+ }
238
+ // Unknown slash command — forward to agent
239
+ return false;
240
+ }
241
+ async handleNew(contextId, msg) {
242
+ const runner = this._runners.get(contextId);
243
+ if (runner) {
244
+ await runner.dispose();
245
+ }
246
+ this._reply(msg, 'New session started.');
247
+ }
248
+ async handleContext(contextId, msg, targetContext) {
249
+ const state = this._getOrCreateContextState(contextId);
250
+ state.peerContextOverride.set(msg.peerId, targetContext);
251
+ this._reply(msg, `Switched to context: ${targetContext}`);
252
+ }
253
+ async handleContexts(_contextId, msg) {
254
+ const names = Array.from(this._runners.keys());
255
+ const contextId = this._resolveContext(msg);
256
+ const lines = names.map(n => (n === contextId ? `* ${n}` : ` ${n}`));
257
+ this._reply(msg, lines.join('\n'));
258
+ }
259
+ async handleStatus(contextId, msg) {
260
+ this._reply(msg, `Context: ${contextId}`);
261
+ }
262
+ async handleCompact(contextId, msg) {
263
+ // Trigger pi session compaction via runner if supported
264
+ const runner = this._runners.get(contextId);
265
+ if (runner?.compact) {
266
+ await runner.compact();
267
+ }
268
+ this._reply(msg, 'Session compacted.');
269
+ }
270
+ // ── Inactivity timer ──────────────────────────────────────────────────────
271
+ _resetInactivityTimer(contextId, state) {
272
+ if (state.inactivityTimer) {
273
+ clearTimeout(state.inactivityTimer);
274
+ }
275
+ const timeoutMs = this._config.session?.inactivityTimeout ?? DEFAULT_INACTIVITY_MS;
276
+ state.inactivityTimer = setTimeout(async () => {
277
+ const runner = this._runners.get(contextId);
278
+ if (runner) {
279
+ await runner.dispose();
280
+ }
281
+ this._contextState.delete(contextId);
282
+ }, timeoutMs);
283
+ }
284
+ // ── Helpers ───────────────────────────────────────────────────────────────
285
+ _getOrCreateContextState(contextId) {
286
+ if (!this._contextState.has(contextId)) {
287
+ this._contextState.set(contextId, {
288
+ busy: false,
289
+ queue: [],
290
+ inactivityTimer: null,
291
+ peerContextOverride: new Map(),
292
+ });
293
+ }
294
+ return this._contextState.get(contextId);
295
+ }
296
+ _reply(msg, text) {
297
+ const adapter = this._adapters.get(msg.channelType);
298
+ if (!adapter)
299
+ return;
300
+ adapter.send(msg.peerId, { type: 'text', text }).catch((err) => {
301
+ console.error(`[Orchestrator] Failed to send reply: ${err}`);
302
+ });
303
+ }
304
+ /** Expose runners for reload/restart */
305
+ get runners() {
306
+ return this._runners;
307
+ }
308
+ /** Expose adapters for restart */
309
+ get adapters() {
310
+ return this._adapters;
311
+ }
312
+ }
313
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Package system
3
+ *
4
+ * installPackage, uninstallPackage, listPackages.
5
+ * Packages are installed to ~/.reeboot/packages/ via npm.
6
+ * Identifiers are stored in config.extensions.packages[].
7
+ */
8
+ export interface PackageOptions {
9
+ /** Path to config.json (default: ~/.reeboot/config.json) */
10
+ configPath?: string;
11
+ /** Reeboot home dir (default: ~/.reeboot) */
12
+ reebotDir?: string;
13
+ }
14
+ export interface InstalledPackage {
15
+ spec: string;
16
+ name: string;
17
+ }
18
+ export declare function installPackage(spec: string, opts?: PackageOptions): Promise<void>;
19
+ export declare function uninstallPackage(name: string, opts?: PackageOptions): Promise<void>;
20
+ export declare function listPackages(opts?: PackageOptions): Promise<InstalledPackage[]>;
21
+ //# sourceMappingURL=packages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packages.d.ts","sourceRoot":"","sources":["../src/packages.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAqDD,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAID,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,IAAI,CAAC,CAiCf;AAID,wBAAsB,YAAY,CAChC,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAW7B"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Package system
3
+ *
4
+ * installPackage, uninstallPackage, listPackages.
5
+ * Packages are installed to ~/.reeboot/packages/ via npm.
6
+ * Identifiers are stored in config.extensions.packages[].
7
+ */
8
+ import { spawnSync } from 'child_process';
9
+ import { readFileSync, writeFileSync, mkdirSync } from 'fs';
10
+ import { join } from 'path';
11
+ import { homedir } from 'os';
12
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
13
+ function getDefaultReebotDir() {
14
+ return join(homedir(), '.reeboot');
15
+ }
16
+ function getDefaultConfigPath(reebotDir) {
17
+ return join(reebotDir, 'config.json');
18
+ }
19
+ function readConfig(configPath) {
20
+ try {
21
+ return JSON.parse(readFileSync(configPath, 'utf-8'));
22
+ }
23
+ catch {
24
+ return {};
25
+ }
26
+ }
27
+ function saveConfig(configPath, config) {
28
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
29
+ }
30
+ /**
31
+ * Convert a spec string (npm:name, git:..., /local/path) to the package name
32
+ * and the npm install argument.
33
+ */
34
+ function parseSpec(spec) {
35
+ if (spec.startsWith('npm:')) {
36
+ const pkgWithVersion = spec.slice(4);
37
+ const name = pkgWithVersion.split('@')[0];
38
+ return { name, npmArg: pkgWithVersion };
39
+ }
40
+ if (spec.startsWith('git:')) {
41
+ // git:github.com/user/repo → github:user/repo
42
+ const path = spec.slice(4);
43
+ const parts = path.split('/');
44
+ if (parts[0].includes('github.com')) {
45
+ const npmArg = `github:${parts.slice(1).join('/')}`;
46
+ const name = parts[parts.length - 1].replace('.git', '');
47
+ return { name, npmArg };
48
+ }
49
+ // Generic git URL
50
+ return { name: spec, npmArg: spec.slice(4) };
51
+ }
52
+ // Local path
53
+ const name = spec.split('/').pop() ?? spec;
54
+ return { name, npmArg: spec };
55
+ }
56
+ // ─── installPackage ───────────────────────────────────────────────────────────
57
+ export async function installPackage(spec, opts = {}) {
58
+ const reebotDir = opts.reebotDir ?? getDefaultReebotDir();
59
+ const configPath = opts.configPath ?? getDefaultConfigPath(reebotDir);
60
+ const packagesDir = join(reebotDir, 'packages');
61
+ mkdirSync(packagesDir, { recursive: true });
62
+ const { name, npmArg } = parseSpec(spec);
63
+ // Run npm install
64
+ const result = spawnSync('npm', ['install', '--prefix', packagesDir, npmArg], { stdio: 'inherit' });
65
+ if (result.status !== 0) {
66
+ throw new Error(`npm install failed for ${spec} (exit code ${result.status})`);
67
+ }
68
+ // Update config
69
+ const config = readConfig(configPath);
70
+ if (!config.extensions)
71
+ config.extensions = {};
72
+ if (!Array.isArray(config.extensions.packages))
73
+ config.extensions.packages = [];
74
+ // Avoid duplicates
75
+ if (!config.extensions.packages.includes(spec)) {
76
+ config.extensions.packages.push(spec);
77
+ }
78
+ saveConfig(configPath, config);
79
+ }
80
+ // ─── uninstallPackage ─────────────────────────────────────────────────────────
81
+ export async function uninstallPackage(name, opts = {}) {
82
+ const reebotDir = opts.reebotDir ?? getDefaultReebotDir();
83
+ const configPath = opts.configPath ?? getDefaultConfigPath(reebotDir);
84
+ const packagesDir = join(reebotDir, 'packages');
85
+ // Find the spec in config
86
+ const config = readConfig(configPath);
87
+ const packages = config.extensions?.packages ?? [];
88
+ // Find matching spec (could be npm:name, git:..., or just name)
89
+ const matchingSpec = packages.find((spec) => {
90
+ const { name: specName } = parseSpec(spec);
91
+ return specName === name || spec === name;
92
+ });
93
+ if (!matchingSpec) {
94
+ throw new Error(`Package not installed: ${name}`);
95
+ }
96
+ // Run npm uninstall
97
+ const result = spawnSync('npm', ['uninstall', '--prefix', packagesDir, name], { stdio: 'inherit' });
98
+ if (result.status !== 0) {
99
+ throw new Error(`npm uninstall failed for ${name} (exit code ${result.status})`);
100
+ }
101
+ // Update config
102
+ config.extensions.packages = packages.filter((spec) => spec !== matchingSpec);
103
+ saveConfig(configPath, config);
104
+ }
105
+ // ─── listPackages ─────────────────────────────────────────────────────────────
106
+ export async function listPackages(opts = {}) {
107
+ const reebotDir = opts.reebotDir ?? getDefaultReebotDir();
108
+ const configPath = opts.configPath ?? getDefaultConfigPath(reebotDir);
109
+ const config = readConfig(configPath);
110
+ const packages = config.extensions?.packages ?? [];
111
+ return packages.map((spec) => {
112
+ const { name } = parseSpec(spec);
113
+ return { spec, name };
114
+ });
115
+ }
116
+ //# sourceMappingURL=packages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packages.js","sourceRoot":"","sources":["../src/packages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Global Scheduler registry singleton.
3
+ * Set by server.ts after the Scheduler is initialised.
4
+ */
5
+ import type { SchedulerToolsTarget } from './scheduler.js';
6
+ export declare let globalScheduler: SchedulerToolsTarget;
7
+ export declare function setGlobalScheduler(scheduler: SchedulerToolsTarget): void;
8
+ //# sourceMappingURL=scheduler-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-registry.d.ts","sourceRoot":"","sources":["../src/scheduler-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAQ3D,eAAO,IAAI,eAAe,EAAE,oBAAoC,CAAC;AAEjE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAExE"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Global Scheduler registry singleton.
3
+ * Set by server.ts after the Scheduler is initialised.
4
+ */
5
+ // Stub scheduler that no-ops until a real one is registered
6
+ const noopScheduler = {
7
+ registerJob: () => { },
8
+ cancelJob: () => { },
9
+ };
10
+ export let globalScheduler = noopScheduler;
11
+ export function setGlobalScheduler(scheduler) {
12
+ globalScheduler = scheduler;
13
+ }
14
+ //# sourceMappingURL=scheduler-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-registry.js","sourceRoot":"","sources":["../src/scheduler-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,4DAA4D;AAC5D,MAAM,aAAa,GAAyB;IAC1C,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC;IACrB,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,IAAI,eAAe,GAAyB,aAAa,CAAC;AAEjE,MAAM,UAAU,kBAAkB,CAAC,SAA+B;IAChE,eAAe,GAAG,SAAS,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Scheduler
3
+ *
4
+ * Loads enabled tasks from the SQLite `tasks` table on startup,
5
+ * registers node-cron jobs, and dispatches prompts to the orchestrator
6
+ * when jobs fire. Updates `last_run` after each execution.
7
+ */
8
+ import type Database from 'better-sqlite3';
9
+ export interface ScheduledTaskRef {
10
+ taskId: string;
11
+ contextId: string;
12
+ prompt: string;
13
+ }
14
+ export interface SchedulerOrchestrator {
15
+ handleScheduledTask(task: ScheduledTaskRef): Promise<void>;
16
+ }
17
+ export declare class Scheduler {
18
+ private _db;
19
+ private _orchestrator;
20
+ private _jobs;
21
+ constructor(db: Database.Database, orchestrator: SchedulerOrchestrator);
22
+ start(): Promise<void>;
23
+ registerJob(task: {
24
+ id: string;
25
+ contextId: string;
26
+ schedule: string;
27
+ prompt: string;
28
+ }): void;
29
+ cancelJob(taskId: string): void;
30
+ stop(): void;
31
+ }
32
+ export interface SchedulerToolsTarget {
33
+ registerJob(task: {
34
+ id: string;
35
+ contextId: string;
36
+ schedule: string;
37
+ prompt: string;
38
+ }): void;
39
+ cancelJob(taskId: string): void;
40
+ }
41
+ export interface ToolResult {
42
+ content: Array<{
43
+ type: 'text';
44
+ text: string;
45
+ }>;
46
+ details: Record<string, unknown>;
47
+ isError?: boolean;
48
+ }
49
+ export declare function createSchedulerTools(db: Database.Database, scheduler: SchedulerToolsTarget): {
50
+ schedule_task(params: {
51
+ schedule: string;
52
+ prompt: string;
53
+ contextId?: string;
54
+ }): Promise<ToolResult>;
55
+ list_tasks(_params: Record<string, never>): Promise<ToolResult>;
56
+ cancel_task(params: {
57
+ task_id: string;
58
+ }): Promise<ToolResult>;
59
+ };
60
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAK3C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAaD,qBAAa,SAAS;IACpB,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,KAAK,CAAuD;gBAExD,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,qBAAqB;IAKhE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B,WAAW,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA2B5F,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ/B,IAAI,IAAI,IAAI;CAMb;AAID,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7F,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,oBAAoB;0BAE3D;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,UAAU,CAAC;wBAsCG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;wBAsB3C;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;EAsBtE"}