openbot 0.1.16 → 0.1.17

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/agent.js CHANGED
@@ -53,7 +53,7 @@ export async function createOpenBot(options) {
53
53
  const baseDir = config.baseDir || DEFAULT_BASE_DIR;
54
54
  const resolvedBaseDir = resolvePath(baseDir);
55
55
  // Parse model configuration
56
- const { provider, modelId } = parseModelString(config.model || "gpt-5-nano");
56
+ const { provider, modelId } = parseModelString(config.model || "gpt-4o-mini");
57
57
  // Tool definitions shared by both providers
58
58
  const toolDefinitions = {
59
59
  ...shellToolDefinitions,
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ const program = new Command();
6
6
  program
7
7
  .name("openbot")
8
8
  .description("OpenBot CLI - Secure and easy configuration")
9
- .version("0.1.15");
9
+ .version("0.1.17");
10
10
  program
11
11
  .command("configure")
12
12
  .description("Configure OpenBot model and settings")
@@ -2,7 +2,6 @@
2
2
  * Initial application layout handler
3
3
  */
4
4
  export async function* initHandler(event) {
5
- console.log(`[InitHandler] Initializing app for platform: ${event.data.platform}`);
6
5
  const thredUI = {
7
6
  type: "thread",
8
7
  props: {
package/dist/server.js CHANGED
@@ -3,8 +3,10 @@ import "dotenv/config";
3
3
  import express from "express";
4
4
  import cors from "cors";
5
5
  import { Command } from "commander";
6
+ import { generateId } from "melony";
6
7
  import { createOpenBot } from "./agent.js";
7
8
  import { loadConfig } from "./config.js";
9
+ import { loadSession, saveSession } from "./session.js";
8
10
  const program = new Command();
9
11
  program
10
12
  .name("openbot-server")
@@ -21,8 +23,6 @@ program
21
23
  openaiApiKey: options.openaiApiKey,
22
24
  anthropicApiKey: options.anthropicApiKey,
23
25
  });
24
- // In-memory state store (use a real database for production)
25
- const stateStore = new Map();
26
26
  app.use(cors());
27
27
  app.use(express.json());
28
28
  app.get("/", async (req, res) => {
@@ -32,14 +32,24 @@ program
32
32
  stream: "Server-Sent Events (SSE)",
33
33
  });
34
34
  });
35
+ // Init endpoint
35
36
  app.get("/api/init", async (req, res) => {
36
37
  const platform = req.query.platform || "web";
38
+ const sessionId = req.query.sessionId || "default";
39
+ const state = await loadSession(sessionId) ?? {};
37
40
  const response = await openBot.jsonResponse({
38
41
  type: "init",
39
42
  data: { platform }
43
+ }, {
44
+ state,
45
+ runId: generateId()
40
46
  });
41
- res.json(await response.json());
47
+ const result = await response.json();
48
+ // Save state in case init handler modified it
49
+ await saveSession(sessionId, state);
50
+ res.json(result);
42
51
  });
52
+ // Chat endpoint
43
53
  app.post("/api/chat", async (req, res) => {
44
54
  const body = req.body;
45
55
  if (!body.event || typeof body.event.type !== "string") {
@@ -54,8 +64,9 @@ program
54
64
  });
55
65
  res.flushHeaders?.();
56
66
  const runtime = openBot.build();
57
- const runId = body.runId ?? "default";
58
- const state = stateStore.get(runId) ?? {};
67
+ const sessionId = body.sessionId ?? "default";
68
+ const runId = body.runId ?? `run_${generateId()}`;
69
+ const state = await loadSession(sessionId) ?? {};
59
70
  const iterator = runtime.run(body.event, {
60
71
  runId,
61
72
  state,
@@ -69,10 +80,12 @@ program
69
80
  if (res.writableEnded) {
70
81
  break;
71
82
  }
83
+ // Log each event to the persistent file
84
+ // await logEvent(sessionId, runId, chunk);
72
85
  res.write(`data: ${JSON.stringify(chunk)}\n\n`);
73
86
  }
74
- // After the run finishes, the state might have been updated by plugins
75
- stateStore.set(runId, state);
87
+ // After the run finishes, save the final state back to disk
88
+ await saveSession(sessionId, state);
76
89
  }
77
90
  catch (error) {
78
91
  console.error("Melony stream error:", error);
@@ -0,0 +1,73 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ const SESSIONS_DIR = path.join(os.homedir(), ".openbot", "sessions");
5
+ function getSessionDir(sessionId) {
6
+ if (!fs.existsSync(SESSIONS_DIR)) {
7
+ const today = new Date().toISOString().slice(0, 10);
8
+ return path.join(SESSIONS_DIR, today, sessionId);
9
+ }
10
+ // 1. Check if it already exists in a date-based folder (YYYY-MM-DD or YYYY-MM)
11
+ const dateFolders = fs.readdirSync(SESSIONS_DIR).filter(d => /^\d{4}-\d{2}(-\d{2})?$/.test(d));
12
+ for (const folder of dateFolders) {
13
+ const dir = path.join(SESSIONS_DIR, folder, sessionId);
14
+ if (fs.existsSync(dir)) {
15
+ return dir;
16
+ }
17
+ }
18
+ // 2. Check if it exists in the root (legacy)
19
+ const legacyDir = path.join(SESSIONS_DIR, sessionId);
20
+ if (fs.existsSync(legacyDir) && fs.statSync(legacyDir).isDirectory()) {
21
+ const stats = fs.statSync(legacyDir);
22
+ const day = stats.mtime.toISOString().slice(0, 10);
23
+ const newDir = path.join(SESSIONS_DIR, day, sessionId);
24
+ fs.mkdirSync(path.dirname(newDir), { recursive: true });
25
+ try {
26
+ fs.renameSync(legacyDir, newDir);
27
+ return newDir;
28
+ }
29
+ catch (error) {
30
+ console.warn(`Failed to migrate session ${sessionId} to ${day}:`, error);
31
+ return legacyDir;
32
+ }
33
+ }
34
+ // 3. New session - use current day
35
+ const today = new Date().toISOString().slice(0, 10);
36
+ return path.join(SESSIONS_DIR, today, sessionId);
37
+ }
38
+ export async function loadSession(sessionId) {
39
+ const sessionDir = getSessionDir(sessionId);
40
+ const statePath = path.join(sessionDir, "state.json");
41
+ if (!fs.existsSync(statePath)) {
42
+ return null;
43
+ }
44
+ try {
45
+ const data = fs.readFileSync(statePath, "utf-8");
46
+ return JSON.parse(data);
47
+ }
48
+ catch (error) {
49
+ console.error(`Failed to load session ${sessionId}:`, error);
50
+ return null;
51
+ }
52
+ }
53
+ export async function saveSession(sessionId, state) {
54
+ const sessionDir = getSessionDir(sessionId);
55
+ if (!fs.existsSync(sessionDir)) {
56
+ fs.mkdirSync(sessionDir, { recursive: true });
57
+ }
58
+ const statePath = path.join(sessionDir, "state.json");
59
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2), "utf-8");
60
+ }
61
+ export async function logEvent(sessionId, runId, event) {
62
+ const sessionDir = getSessionDir(sessionId);
63
+ if (!fs.existsSync(sessionDir)) {
64
+ fs.mkdirSync(sessionDir, { recursive: true });
65
+ }
66
+ const logPath = path.join(sessionDir, `events.jsonl`);
67
+ const entry = JSON.stringify({
68
+ timestamp: new Date().toISOString(),
69
+ runId,
70
+ ...event,
71
+ });
72
+ fs.appendFileSync(logPath, entry + "\n", "utf-8");
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openbot",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,10 +17,10 @@
17
17
  "express": "^4.19.2",
18
18
  "zod": "^4.3.5",
19
19
  "@melony/plugin-ai-sdk": "0.1.4",
20
+ "@melony/plugin-file-system": "0.1.1",
20
21
  "@melony/plugin-browser": "0.1.3",
21
- "@melony/plugin-meta-agent": "0.1.2",
22
22
  "@melony/plugin-shell": "0.1.1",
23
- "@melony/plugin-file-system": "0.1.1",
23
+ "@melony/plugin-meta-agent": "0.1.2",
24
24
  "melony": "0.2.6"
25
25
  },
26
26
  "devDependencies": {