openbot 0.2.2 → 0.2.3

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/cli.js CHANGED
@@ -13,7 +13,7 @@ const program = new Command();
13
13
  program
14
14
  .name("openbot")
15
15
  .description("OpenBot CLI - Secure and easy configuration")
16
- .version("0.2.2");
16
+ .version("0.2.3");
17
17
  /**
18
18
  * Check if a GitHub repository exists.
19
19
  */
package/dist/server.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import "dotenv/config";
2
2
  import express from "express";
3
3
  import cors from "cors";
4
+ import chokidar from "chokidar";
4
5
  import { generateId } from "melony";
5
6
  import { createOpenBot } from "./open-bot.js";
6
7
  import { loadConfig, saveConfig, isConfigured, resolvePath, DEFAULT_BASE_DIR } from "./config.js";
@@ -17,10 +18,78 @@ export async function startServer(options = {}) {
17
18
  const config = loadConfig();
18
19
  const PORT = Number(options.port ?? config.port ?? process.env.PORT ?? 4001);
19
20
  const app = express();
20
- const orchestrator = await createOpenBot({
21
+ const createOrchestrator = () => createOpenBot({
21
22
  openaiApiKey: options.openaiApiKey,
22
23
  anthropicApiKey: options.anthropicApiKey,
23
24
  });
25
+ let orchestrator = await createOrchestrator();
26
+ let reloadTimer = null;
27
+ let reloadInProgress = false;
28
+ let queuedReload = false;
29
+ const reloadOrchestrator = async () => {
30
+ if (reloadInProgress) {
31
+ queuedReload = true;
32
+ return;
33
+ }
34
+ reloadInProgress = true;
35
+ try {
36
+ const nextOrchestrator = await createOrchestrator();
37
+ orchestrator = nextOrchestrator;
38
+ console.log("[hot-reload] Orchestrator reloaded from ~/.openbot changes");
39
+ }
40
+ catch (error) {
41
+ console.error("[hot-reload] Reload failed; keeping previous orchestrator", error);
42
+ }
43
+ finally {
44
+ reloadInProgress = false;
45
+ if (queuedReload) {
46
+ queuedReload = false;
47
+ scheduleReload();
48
+ }
49
+ }
50
+ };
51
+ const scheduleReload = () => {
52
+ if (reloadTimer)
53
+ clearTimeout(reloadTimer);
54
+ reloadTimer = setTimeout(() => {
55
+ reloadTimer = null;
56
+ void reloadOrchestrator();
57
+ }, 800);
58
+ };
59
+ const openBotDir = path.join(os.homedir(), ".openbot");
60
+ const watcher = chokidar.watch([
61
+ path.join(openBotDir, "config.json"),
62
+ path.join(openBotDir, "agents", "**", "*"),
63
+ path.join(openBotDir, "plugins", "**", "*"),
64
+ ], {
65
+ ignoreInitial: true,
66
+ awaitWriteFinish: {
67
+ stabilityThreshold: 300,
68
+ pollInterval: 100,
69
+ },
70
+ });
71
+ watcher
72
+ .on("add", scheduleReload)
73
+ .on("change", scheduleReload)
74
+ .on("unlink", scheduleReload)
75
+ .on("addDir", scheduleReload)
76
+ .on("unlinkDir", scheduleReload)
77
+ .on("error", (error) => {
78
+ console.error("[hot-reload] Watcher error", error);
79
+ });
80
+ const cleanupWatcher = async () => {
81
+ if (reloadTimer) {
82
+ clearTimeout(reloadTimer);
83
+ reloadTimer = null;
84
+ }
85
+ await watcher.close();
86
+ };
87
+ process.once("SIGINT", () => {
88
+ void cleanupWatcher().finally(() => process.exit(0));
89
+ });
90
+ process.once("SIGTERM", () => {
91
+ void cleanupWatcher().finally(() => process.exit(0));
92
+ });
24
93
  app.use(cors());
25
94
  app.use(express.json({ limit: "20mb" }));
26
95
  const getUploadsDir = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openbot",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,6 +12,7 @@
12
12
  "@melony/ui-kit": "^0.1.30",
13
13
  "@types/cors": "^2.8.19",
14
14
  "ai": "^6.0.42",
15
+ "chokidar": "^5.0.0",
15
16
  "commander": "^14.0.2",
16
17
  "cors": "^2.8.6",
17
18
  "dotenv": "^16.4.5",