openbot 0.2.11 → 0.2.13
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/.prettierrc +8 -0
- package/AGENTS.md +68 -0
- package/CONTRIBUTING.md +74 -0
- package/LICENSE +21 -0
- package/README.md +117 -14
- package/dist/agents/system.js +106 -0
- package/dist/app/cli.js +27 -0
- package/dist/app/config.js +64 -0
- package/dist/app/server.js +237 -0
- package/dist/app/utils.js +35 -0
- package/dist/harness/agent-harness.js +45 -0
- package/dist/harness/mcp.js +61 -0
- package/dist/harness/orchestrator.js +273 -0
- package/dist/harness/process.js +7 -0
- package/dist/plugins/ai-sdk.js +141 -0
- package/dist/plugins/delegation.js +52 -0
- package/dist/plugins/mcp.js +140 -0
- package/dist/plugins/storage.js +502 -0
- package/dist/plugins/ui.js +47 -0
- package/dist/registry/plugins.js +73 -0
- package/dist/services/storage.js +724 -0
- package/docs/README.md +7 -0
- package/docs/agents.md +83 -0
- package/docs/architecture.md +34 -0
- package/docs/plugins.md +77 -0
- package/logo-black.png +0 -0
- package/{dist/assets/logo.js → logo-black.svg} +24 -24
- package/{dist/ui/sidebar.js → logo-white.svg} +23 -88
- package/package.json +10 -9
- package/src/agents/system.ts +112 -0
- package/src/app/cli.ts +38 -0
- package/src/app/config.ts +104 -0
- package/src/app/server.ts +284 -0
- package/src/app/types.ts +476 -0
- package/src/app/utils.ts +43 -0
- package/src/assets/icon.svg +1 -0
- package/src/harness/agent-harness.ts +58 -0
- package/src/harness/mcp.ts +78 -0
- package/src/harness/orchestrator.ts +342 -0
- package/src/harness/process.ts +9 -0
- package/src/harness/types.ts +34 -0
- package/src/plugins/ai-sdk.ts +197 -0
- package/src/plugins/delegation.ts +60 -0
- package/src/plugins/mcp.ts +154 -0
- package/src/plugins/storage.ts +725 -0
- package/src/plugins/ui.ts +57 -0
- package/src/registry/plugins.ts +85 -0
- package/src/services/storage.ts +957 -0
- package/tsconfig.json +18 -0
- package/dist/agents/agent-creator.js +0 -74
- package/dist/agents/browser-agent.js +0 -31
- package/dist/agents/os-agent.js +0 -32
- package/dist/agents/planner-agent.js +0 -32
- package/dist/agents/topic-agent.js +0 -46
- package/dist/architecture/execution-engine.js +0 -151
- package/dist/architecture/intent-classifier.js +0 -26
- package/dist/architecture/planner.js +0 -106
- package/dist/automation-worker.js +0 -121
- package/dist/automations.js +0 -52
- package/dist/cli.js +0 -275
- package/dist/config.js +0 -53
- package/dist/core/agents.js +0 -41
- package/dist/core/delegation.js +0 -230
- package/dist/core/manager.js +0 -96
- package/dist/core/plugins.js +0 -74
- package/dist/core/router.js +0 -191
- package/dist/handlers/init.js +0 -29
- package/dist/handlers/session-change.js +0 -21
- package/dist/handlers/settings.js +0 -47
- package/dist/handlers/tab-change.js +0 -14
- package/dist/installers.js +0 -156
- package/dist/marketplace.js +0 -80
- package/dist/model-catalog.js +0 -132
- package/dist/model-defaults.js +0 -25
- package/dist/models.js +0 -47
- package/dist/open-bot.js +0 -51
- package/dist/orchestrator/direct-invocation.js +0 -13
- package/dist/orchestrator/events.js +0 -36
- package/dist/orchestrator/state.js +0 -54
- package/dist/orchestrator.js +0 -422
- package/dist/plugins/agent/index.js +0 -81
- package/dist/plugins/approval/index.js +0 -100
- package/dist/plugins/brain/identity.js +0 -77
- package/dist/plugins/brain/index.js +0 -204
- package/dist/plugins/brain/memory.js +0 -120
- package/dist/plugins/brain/prompt.js +0 -46
- package/dist/plugins/brain/types.js +0 -45
- package/dist/plugins/brain/ui.js +0 -7
- package/dist/plugins/browser/index.js +0 -629
- package/dist/plugins/browser/ui.js +0 -13
- package/dist/plugins/file-system/index.js +0 -171
- package/dist/plugins/file-system/ui.js +0 -6
- package/dist/plugins/llm/context-budget.js +0 -139
- package/dist/plugins/llm/context-shaping.js +0 -177
- package/dist/plugins/llm/index.js +0 -380
- package/dist/plugins/memory/index.js +0 -220
- package/dist/plugins/memory/memory.js +0 -122
- package/dist/plugins/memory/prompt.js +0 -55
- package/dist/plugins/memory/types.js +0 -45
- package/dist/plugins/meta-agent/index.js +0 -570
- package/dist/plugins/meta-agent/ui.js +0 -11
- package/dist/plugins/shell/index.js +0 -100
- package/dist/plugins/shell/ui.js +0 -6
- package/dist/plugins/skills/index.js +0 -286
- package/dist/plugins/skills/types.js +0 -50
- package/dist/plugins/skills/ui.js +0 -12
- package/dist/registry/agent-registry.js +0 -35
- package/dist/registry/index.js +0 -2
- package/dist/registry/plugin-loader.js +0 -499
- package/dist/registry/plugin-registry.js +0 -44
- package/dist/registry/ts-agent-loader.js +0 -82
- package/dist/registry/yaml-agent-loader.js +0 -246
- package/dist/runtime/execution-trace.js +0 -41
- package/dist/runtime/intent-routing.js +0 -26
- package/dist/runtime/openbot-runtime.js +0 -354
- package/dist/server.js +0 -890
- package/dist/session.js +0 -179
- package/dist/ui/block.js +0 -12
- package/dist/ui/header.js +0 -52
- package/dist/ui/layout.js +0 -26
- package/dist/ui/navigation.js +0 -15
- package/dist/ui/settings.js +0 -106
- package/dist/ui/skills.js +0 -7
- package/dist/ui/thread.js +0 -16
- package/dist/ui/widgets/action-list.js +0 -2
- package/dist/ui/widgets/approval-card.js +0 -9
- package/dist/ui/widgets/code-snippet.js +0 -2
- package/dist/ui/widgets/data-block.js +0 -2
- package/dist/ui/widgets/data-table.js +0 -2
- package/dist/ui/widgets/delegation.js +0 -29
- package/dist/ui/widgets/empty-state.js +0 -2
- package/dist/ui/widgets/index.js +0 -23
- package/dist/ui/widgets/inquiry.js +0 -7
- package/dist/ui/widgets/key-value.js +0 -2
- package/dist/ui/widgets/progress-step.js +0 -2
- package/dist/ui/widgets/resource-card.js +0 -2
- package/dist/ui/widgets/status.js +0 -2
- package/dist/ui/widgets/todo-list.js +0 -2
- package/dist/version.js +0 -62
- /package/dist/{types.js → app/types.js} +0 -0
- /package/dist/{architecture/contracts.js → harness/types.js} +0 -0
package/dist/session.js
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
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
|
-
/**
|
|
39
|
-
* Maximum number of messages to keep when loading a session.
|
|
40
|
-
* Older messages are dropped to avoid bloated context windows.
|
|
41
|
-
* System messages at the start are always preserved and don't count toward the limit.
|
|
42
|
-
*/
|
|
43
|
-
const MAX_MESSAGES = 1000; // aiSdkPlugin defaults to latest 20 messages
|
|
44
|
-
const MAX_LISTED_SESSIONS = 1000;
|
|
45
|
-
function hasPersistedContent(state) {
|
|
46
|
-
if (state.title)
|
|
47
|
-
return true;
|
|
48
|
-
if (state.messages && state.messages.length > 0)
|
|
49
|
-
return true;
|
|
50
|
-
// Direct sub-agent conversations are stored under agentStates.
|
|
51
|
-
// Treat any non-empty agent state as a persisted session.
|
|
52
|
-
if (state.agentStates && typeof state.agentStates === "object") {
|
|
53
|
-
for (const agentState of Object.values(state.agentStates)) {
|
|
54
|
-
if (!agentState || typeof agentState !== "object")
|
|
55
|
-
continue;
|
|
56
|
-
if (Object.keys(agentState).length > 0)
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
export async function loadSession(sessionId) {
|
|
63
|
-
const sessionDir = getSessionDir(sessionId);
|
|
64
|
-
const statePath = path.join(sessionDir, "state.json");
|
|
65
|
-
if (!fs.existsSync(statePath)) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
try {
|
|
69
|
-
const data = fs.readFileSync(statePath, "utf-8");
|
|
70
|
-
const state = JSON.parse(data);
|
|
71
|
-
if (state.messages && state.messages.length > MAX_MESSAGES) {
|
|
72
|
-
// Preserve system messages at the beginning, then keep the tail
|
|
73
|
-
const systemMessages = [];
|
|
74
|
-
let rest = state.messages;
|
|
75
|
-
while (rest.length > 0 && rest[0].role === "system") {
|
|
76
|
-
systemMessages.push(rest[0]);
|
|
77
|
-
rest = rest.slice(1);
|
|
78
|
-
}
|
|
79
|
-
const kept = rest.slice(-MAX_MESSAGES);
|
|
80
|
-
state.messages = [...systemMessages, ...kept];
|
|
81
|
-
}
|
|
82
|
-
return state;
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
console.error(`Failed to load session ${sessionId}:`, error);
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
export async function saveSession(sessionId, state) {
|
|
90
|
-
const sessionDir = getSessionDir(sessionId);
|
|
91
|
-
if (!fs.existsSync(sessionDir)) {
|
|
92
|
-
fs.mkdirSync(sessionDir, { recursive: true });
|
|
93
|
-
}
|
|
94
|
-
const statePath = path.join(sessionDir, "state.json");
|
|
95
|
-
fs.writeFileSync(statePath, JSON.stringify(state, null, 2), "utf-8");
|
|
96
|
-
}
|
|
97
|
-
export async function logEvent(sessionId, runId, event) {
|
|
98
|
-
const sessionDir = getSessionDir(sessionId);
|
|
99
|
-
if (!fs.existsSync(sessionDir)) {
|
|
100
|
-
fs.mkdirSync(sessionDir, { recursive: true });
|
|
101
|
-
}
|
|
102
|
-
const logPath = path.join(sessionDir, `events.jsonl`);
|
|
103
|
-
const entry = JSON.stringify({
|
|
104
|
-
timestamp: new Date().toISOString(),
|
|
105
|
-
runId,
|
|
106
|
-
...event,
|
|
107
|
-
});
|
|
108
|
-
fs.appendFileSync(logPath, entry + "\n", "utf-8");
|
|
109
|
-
}
|
|
110
|
-
export async function loadEvents(sessionId) {
|
|
111
|
-
const sessionDir = getSessionDir(sessionId);
|
|
112
|
-
const logPath = path.join(sessionDir, `events.jsonl`);
|
|
113
|
-
if (!fs.existsSync(logPath)) {
|
|
114
|
-
return [];
|
|
115
|
-
}
|
|
116
|
-
try {
|
|
117
|
-
const data = fs.readFileSync(logPath, "utf-8");
|
|
118
|
-
return data
|
|
119
|
-
.split("\n")
|
|
120
|
-
.filter((line) => line.trim() !== "")
|
|
121
|
-
.map((line) => JSON.parse(line));
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
console.error(`Failed to load events for session ${sessionId}:`, error);
|
|
125
|
-
return [];
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
export async function listSessions() {
|
|
129
|
-
if (!fs.existsSync(SESSIONS_DIR))
|
|
130
|
-
return [];
|
|
131
|
-
const sessions = [];
|
|
132
|
-
try {
|
|
133
|
-
const items = fs.readdirSync(SESSIONS_DIR);
|
|
134
|
-
for (const item of items) {
|
|
135
|
-
const itemPath = path.join(SESSIONS_DIR, item);
|
|
136
|
-
const stat = fs.statSync(itemPath);
|
|
137
|
-
if (stat.isDirectory()) {
|
|
138
|
-
// If it's a date folder (YYYY-MM-DD), look inside
|
|
139
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(item)) {
|
|
140
|
-
const subItems = fs.readdirSync(itemPath);
|
|
141
|
-
for (const subItem of subItems) {
|
|
142
|
-
const sessionPath = path.join(itemPath, subItem);
|
|
143
|
-
const statePath = path.join(sessionPath, "state.json");
|
|
144
|
-
if (fs.existsSync(statePath)) {
|
|
145
|
-
const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
|
|
146
|
-
if (hasPersistedContent(state)) {
|
|
147
|
-
sessions.push({
|
|
148
|
-
id: subItem,
|
|
149
|
-
mtime: fs.statSync(statePath).birthtime, // sort by creation time
|
|
150
|
-
title: state.title ?? undefined,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
// It's a legacy session folder in root
|
|
158
|
-
const statePath = path.join(itemPath, "state.json");
|
|
159
|
-
if (fs.existsSync(statePath)) {
|
|
160
|
-
const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
|
|
161
|
-
if (hasPersistedContent(state)) {
|
|
162
|
-
sessions.push({
|
|
163
|
-
id: item,
|
|
164
|
-
title: state.title ?? undefined,
|
|
165
|
-
mtime: fs.statSync(statePath).birthtime, // sort by creation time
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
catch (error) {
|
|
174
|
-
console.error("Failed to list sessions:", error);
|
|
175
|
-
}
|
|
176
|
-
return sessions
|
|
177
|
-
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())
|
|
178
|
-
.slice(0, MAX_LISTED_SESSIONS);
|
|
179
|
-
}
|
package/dist/ui/block.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export const block = (widget, props, options = {}) => ({
|
|
2
|
-
type: "ui-block",
|
|
3
|
-
widget,
|
|
4
|
-
props,
|
|
5
|
-
placement: options.placement ?? "thread",
|
|
6
|
-
id: options.id,
|
|
7
|
-
meta: options.meta,
|
|
8
|
-
});
|
|
9
|
-
export const uiEvent = (block) => ({
|
|
10
|
-
type: "ui",
|
|
11
|
-
data: block,
|
|
12
|
-
});
|
package/dist/ui/header.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { ui } from "@melony/ui-kit";
|
|
2
|
-
export const headerUI = (tab) => ui.box({
|
|
3
|
-
padding: "sm",
|
|
4
|
-
background: "background",
|
|
5
|
-
width: "full",
|
|
6
|
-
}, [
|
|
7
|
-
ui.row({ justify: "between", align: "center", width: "full" }, [
|
|
8
|
-
ui.row({ gap: "xs", align: "center" }, [
|
|
9
|
-
ui.listItem({
|
|
10
|
-
onClickAction: {
|
|
11
|
-
type: "client:navigate",
|
|
12
|
-
data: { path: "/" }
|
|
13
|
-
}
|
|
14
|
-
}, [ui.text("OpenBot")]),
|
|
15
|
-
ui.divider({ orientation: "vertical", margin: "xs" }),
|
|
16
|
-
ui.button({
|
|
17
|
-
label: "Chat",
|
|
18
|
-
variant: (tab === "chat" || !tab) ? "secondary" : "ghost",
|
|
19
|
-
size: "sm",
|
|
20
|
-
onClickAction: {
|
|
21
|
-
type: "client:navigate",
|
|
22
|
-
data: { path: "/" },
|
|
23
|
-
},
|
|
24
|
-
}),
|
|
25
|
-
ui.button({
|
|
26
|
-
label: "Skills",
|
|
27
|
-
variant: tab === "skills" ? "secondary" : "ghost",
|
|
28
|
-
size: "sm",
|
|
29
|
-
onClickAction: {
|
|
30
|
-
type: "client:navigate",
|
|
31
|
-
data: { path: "/?tab=skills" },
|
|
32
|
-
},
|
|
33
|
-
}),
|
|
34
|
-
ui.button({
|
|
35
|
-
label: "Settings",
|
|
36
|
-
variant: tab === "settings" ? "secondary" : "ghost",
|
|
37
|
-
size: "sm",
|
|
38
|
-
onClickAction: {
|
|
39
|
-
type: "client:navigate",
|
|
40
|
-
data: { path: "/?tab=settings" },
|
|
41
|
-
},
|
|
42
|
-
}),
|
|
43
|
-
]),
|
|
44
|
-
ui.row({ gap: "sm", align: "center", width: "auto" }, [
|
|
45
|
-
ui.button({
|
|
46
|
-
label: "JD",
|
|
47
|
-
variant: "outline",
|
|
48
|
-
size: "sm",
|
|
49
|
-
}),
|
|
50
|
-
]),
|
|
51
|
-
]),
|
|
52
|
-
]);
|
package/dist/ui/layout.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ui } from "@melony/ui-kit";
|
|
2
|
-
import { threadUI } from "./thread.js";
|
|
3
|
-
import { sidebarUI } from "./sidebar.js";
|
|
4
|
-
import { settingsUI } from "./settings.js";
|
|
5
|
-
import { skillsUI } from "./skills.js";
|
|
6
|
-
import { listSessions } from "../session.js";
|
|
7
|
-
const tabs = {
|
|
8
|
-
chat: threadUI,
|
|
9
|
-
settings: settingsUI,
|
|
10
|
-
skills: skillsUI,
|
|
11
|
-
};
|
|
12
|
-
export const layoutUI = async ({ tab, sessionId }) => {
|
|
13
|
-
const sessions = await listSessions();
|
|
14
|
-
const content = typeof tabs[tab] === "function" ? await tabs[tab]() : tabs[tab];
|
|
15
|
-
return ui.row({ height: "full" }, [
|
|
16
|
-
sidebarUI({ sessions, sessionId }),
|
|
17
|
-
content
|
|
18
|
-
]);
|
|
19
|
-
};
|
|
20
|
-
export const sidebarOnlyUI = async ({ sessionId }) => {
|
|
21
|
-
const sessions = await listSessions();
|
|
22
|
-
return sidebarUI({ sessions, sessionId });
|
|
23
|
-
};
|
|
24
|
-
export const tabOnlyUI = async ({ tab }) => {
|
|
25
|
-
return typeof tabs[tab] === "function" ? await tabs[tab]() : tabs[tab];
|
|
26
|
-
};
|
package/dist/ui/navigation.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ui } from "@melony/ui-kit";
|
|
2
|
-
const listItemProps = (path) => ({
|
|
3
|
-
onClickAction: {
|
|
4
|
-
type: "client:navigate",
|
|
5
|
-
data: { path },
|
|
6
|
-
},
|
|
7
|
-
});
|
|
8
|
-
export const navigationUI = ui.box({ width: "full" }, [ui.list({
|
|
9
|
-
gap: "none",
|
|
10
|
-
}, [
|
|
11
|
-
ui.listItem(listItemProps("/"), [
|
|
12
|
-
ui.icon("PlusIcon", { size: "sm" }),
|
|
13
|
-
ui.text("New chat", { size: "sm" })
|
|
14
|
-
])
|
|
15
|
-
])]);
|
package/dist/ui/settings.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { ui } from "@melony/ui-kit";
|
|
2
|
-
import { loadConfig, resolvePath, DEFAULT_BASE_DIR } from "../config.js";
|
|
3
|
-
import { listYamlAgents } from "../registry/index.js";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
export const settingsUI = async () => {
|
|
6
|
-
const config = loadConfig();
|
|
7
|
-
const baseDir = config.baseDir || DEFAULT_BASE_DIR;
|
|
8
|
-
const resolvedBaseDir = resolvePath(baseDir);
|
|
9
|
-
const agentsDir = path.join(resolvedBaseDir, "agents");
|
|
10
|
-
const hasOpenAIKey = !!config.openaiApiKey;
|
|
11
|
-
const hasAnthropicKey = !!config.anthropicApiKey;
|
|
12
|
-
const agents = await listYamlAgents(agentsDir);
|
|
13
|
-
return ui.box({
|
|
14
|
-
width: "full",
|
|
15
|
-
height: "full",
|
|
16
|
-
overflow: "auto",
|
|
17
|
-
}, [
|
|
18
|
-
ui.col({ padding: "xl", gap: "xl", width: "full", flex: 1 }, [
|
|
19
|
-
ui.col({ gap: "xs" }, [
|
|
20
|
-
ui.heading("Settings", 2),
|
|
21
|
-
ui.text("Manage your OpenBot configuration", { color: "mutedForeground" }),
|
|
22
|
-
]),
|
|
23
|
-
ui.divider(),
|
|
24
|
-
ui.form({
|
|
25
|
-
onSubmitAction: {
|
|
26
|
-
type: "action:updateSettings",
|
|
27
|
-
data: {}
|
|
28
|
-
}
|
|
29
|
-
}, [
|
|
30
|
-
ui.col({ gap: "xl" }, [
|
|
31
|
-
ui.col({ gap: "md" }, [
|
|
32
|
-
ui.heading("Model Configuration", 4),
|
|
33
|
-
ui.col({ gap: "sm" }, [
|
|
34
|
-
ui.input("model", undefined, {
|
|
35
|
-
placeholder: "provider/model (e.g. openai/gpt-4o)",
|
|
36
|
-
width: "full",
|
|
37
|
-
defaultValue: config.model || "openai/gpt-4o-mini"
|
|
38
|
-
}),
|
|
39
|
-
]),
|
|
40
|
-
]),
|
|
41
|
-
ui.col({ gap: "md" }, [
|
|
42
|
-
ui.heading("API Keys", 4),
|
|
43
|
-
ui.col({ gap: "lg" }, [
|
|
44
|
-
// OpenAI Key
|
|
45
|
-
ui.col({ gap: "sm" }, [
|
|
46
|
-
ui.node("label", { value: "OpenAI API Key" }),
|
|
47
|
-
ui.input("openai_api_key", undefined, {
|
|
48
|
-
placeholder: "sk-...",
|
|
49
|
-
inputType: "password",
|
|
50
|
-
defaultValue: hasOpenAIKey ? "••••••••••••••••" : "",
|
|
51
|
-
width: "full"
|
|
52
|
-
}),
|
|
53
|
-
]),
|
|
54
|
-
// Anthropic Key
|
|
55
|
-
ui.col({ gap: "sm" }, [
|
|
56
|
-
ui.node("label", { value: "Anthropic API Key" }),
|
|
57
|
-
ui.input("anthropic_api_key", undefined, {
|
|
58
|
-
placeholder: "sk-ant-...",
|
|
59
|
-
inputType: "password",
|
|
60
|
-
defaultValue: hasAnthropicKey ? "••••••••••••••••" : "",
|
|
61
|
-
width: "full"
|
|
62
|
-
}),
|
|
63
|
-
])
|
|
64
|
-
])
|
|
65
|
-
]),
|
|
66
|
-
ui.col({ gap: "md" }, [
|
|
67
|
-
ui.heading("Theme", 4),
|
|
68
|
-
ui.themeToggle(),
|
|
69
|
-
]),
|
|
70
|
-
ui.row({ justify: "end" }, [
|
|
71
|
-
ui.button({
|
|
72
|
-
label: "Save Settings",
|
|
73
|
-
type: "submit",
|
|
74
|
-
variant: "primary"
|
|
75
|
-
})
|
|
76
|
-
])
|
|
77
|
-
])
|
|
78
|
-
]),
|
|
79
|
-
ui.divider(),
|
|
80
|
-
ui.col({ gap: "md" }, [
|
|
81
|
-
ui.heading("Installed Agents", 4),
|
|
82
|
-
ui.text("Agents installed in ~/.openbot/agents", { color: "mutedForeground", size: "sm" }),
|
|
83
|
-
ui.col({ gap: "sm" }, agents.map(agent => (ui.box({
|
|
84
|
-
padding: "md",
|
|
85
|
-
background: "muted",
|
|
86
|
-
}, [
|
|
87
|
-
ui.row({ justify: "between", align: "center" }, [
|
|
88
|
-
ui.col({ gap: "xs" }, [
|
|
89
|
-
ui.text(agent.name, { weight: "bold" }),
|
|
90
|
-
ui.text(agent.description, { size: "sm", color: "mutedForeground" }),
|
|
91
|
-
]),
|
|
92
|
-
ui.button({
|
|
93
|
-
label: "Open Folder",
|
|
94
|
-
variant: "secondary",
|
|
95
|
-
size: "sm",
|
|
96
|
-
onClickAction: {
|
|
97
|
-
type: "action:openAgentFolder",
|
|
98
|
-
data: { folder: agent.folder }
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
])
|
|
102
|
-
]))))
|
|
103
|
-
])
|
|
104
|
-
]),
|
|
105
|
-
]);
|
|
106
|
-
};
|
package/dist/ui/skills.js
DELETED
package/dist/ui/thread.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ui } from "@melony/ui-kit";
|
|
2
|
-
export const threadUI = ui.box({
|
|
3
|
-
width: "full",
|
|
4
|
-
height: "full",
|
|
5
|
-
}, [ui.thread({
|
|
6
|
-
placeholder: "Ask me anything about your system or projects...",
|
|
7
|
-
}, [
|
|
8
|
-
ui.heading("Hey there!"),
|
|
9
|
-
ui.text("I'm your trusty system sidekick with superpowers over your files and terminal. Let's make some magic happen!", { size: "sm", color: "mutedForeground" }),
|
|
10
|
-
ui.col({ gap: "sm" }, [
|
|
11
|
-
ui.button({ onClickAction: { type: "user:text", data: { content: "What is in my current directory?" } }, label: "What is in my current directory?", size: "sm", variant: "outline" }),
|
|
12
|
-
ui.button({ onClickAction: { type: "user:text", data: { content: "Check system status" } }, label: "Check system status", size: "sm", variant: "outline" }),
|
|
13
|
-
ui.button({ onClickAction: { type: "user:text", data: { content: "Who am I?" } }, label: "Who am I?", size: "sm", variant: "outline" }),
|
|
14
|
-
ui.button({ onClickAction: { type: "user:text", data: { content: "Who are you?" } }, label: "Who are you?", size: "sm", variant: "outline" }),
|
|
15
|
-
]),
|
|
16
|
-
])]);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { block } from '../block.js';
|
|
2
|
-
export const approvalCard = (title, data, approveAction, denyAction, options = {}) => block('approval-card', {
|
|
3
|
-
title,
|
|
4
|
-
summary: data.summary,
|
|
5
|
-
details: data.details,
|
|
6
|
-
rawPayload: data.rawPayload,
|
|
7
|
-
approveAction,
|
|
8
|
-
denyAction
|
|
9
|
-
}, options);
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { ui } from "@melony/ui-kit/server";
|
|
2
|
-
function stateLabel(state) {
|
|
3
|
-
if (state === "running")
|
|
4
|
-
return "Running";
|
|
5
|
-
if (state === "completed")
|
|
6
|
-
return "Completed";
|
|
7
|
-
return "Failed";
|
|
8
|
-
}
|
|
9
|
-
export const delegationWidget = (agentName, state, task, details) => {
|
|
10
|
-
const taskPreview = (task || "").trim();
|
|
11
|
-
const clippedTask = taskPreview.length > 240
|
|
12
|
-
? `${taskPreview.slice(0, 237)}...`
|
|
13
|
-
: taskPreview;
|
|
14
|
-
const detailsPreview = (details || "").trim();
|
|
15
|
-
const clippedDetails = detailsPreview.length > 400
|
|
16
|
-
? `${detailsPreview.slice(0, 397)}...`
|
|
17
|
-
: detailsPreview;
|
|
18
|
-
return ui.box({ border: true, radius: "md", padding: "md" }, [
|
|
19
|
-
ui.col({ gap: "sm" }, [
|
|
20
|
-
ui.heading(`Sub-agent: ${agentName}`, { level: 4 }),
|
|
21
|
-
ui.text(`State: ${stateLabel(state)}`, {
|
|
22
|
-
size: "xs",
|
|
23
|
-
color: state === "failed" ? "danger" : state === "completed" ? "success" : "muted",
|
|
24
|
-
}),
|
|
25
|
-
...(clippedTask ? [ui.text(`Task: ${clippedTask}`, { size: "sm", color: "muted" })] : []),
|
|
26
|
-
...(clippedDetails ? [ui.text(clippedDetails, { size: "sm" })] : []),
|
|
27
|
-
]),
|
|
28
|
-
]);
|
|
29
|
-
};
|
package/dist/ui/widgets/index.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { keyValue } from './key-value.js';
|
|
2
|
-
import { dataTable } from './data-table.js';
|
|
3
|
-
import { codeSnippet } from './code-snippet.js';
|
|
4
|
-
import { statusWidget as status } from './status.js';
|
|
5
|
-
import { progressStep } from './progress-step.js';
|
|
6
|
-
import { approvalCard } from './approval-card.js';
|
|
7
|
-
import { actionList } from './action-list.js';
|
|
8
|
-
import { emptyState } from './empty-state.js';
|
|
9
|
-
import { todoList } from './todo-list.js';
|
|
10
|
-
import { inquiryCard } from './inquiry.js';
|
|
11
|
-
export const widgets = {
|
|
12
|
-
keyValue,
|
|
13
|
-
dataTable,
|
|
14
|
-
codeSnippet,
|
|
15
|
-
status,
|
|
16
|
-
progressStep,
|
|
17
|
-
approvalCard,
|
|
18
|
-
actionList,
|
|
19
|
-
emptyState,
|
|
20
|
-
todoList,
|
|
21
|
-
inquiryCard,
|
|
22
|
-
};
|
|
23
|
-
export default widgets;
|
package/dist/version.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
/**
|
|
5
|
-
* Gets the version of the currently running OpenBot instance.
|
|
6
|
-
* Works regardless of where the command is executed from.
|
|
7
|
-
*/
|
|
8
|
-
export function getCurrentVersion() {
|
|
9
|
-
try {
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = dirname(__filename);
|
|
12
|
-
// Look for package.json by walking up from the current directory
|
|
13
|
-
let currentDir = __dirname;
|
|
14
|
-
for (let i = 0; i < 4; i++) {
|
|
15
|
-
const pkgPath = join(currentDir, "package.json");
|
|
16
|
-
try {
|
|
17
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
18
|
-
if (pkg.name === "openbot") {
|
|
19
|
-
return pkg.version;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
// Continue walking up
|
|
24
|
-
}
|
|
25
|
-
currentDir = dirname(currentDir);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
console.warn("Could not determine OpenBot version:", err);
|
|
30
|
-
}
|
|
31
|
-
// Fallback to a hardcoded version if detection fails
|
|
32
|
-
return "0.2.3";
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Fetches the latest version from NPM registry and checks for updates.
|
|
36
|
-
*/
|
|
37
|
-
export async function getVersionStatus() {
|
|
38
|
-
const current = getCurrentVersion();
|
|
39
|
-
try {
|
|
40
|
-
const response = await fetch("https://registry.npmjs.org/openbot/latest", {
|
|
41
|
-
signal: AbortSignal.timeout(5000), // 5s timeout
|
|
42
|
-
});
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
throw new Error(`NPM registry returned ${response.status}`);
|
|
45
|
-
}
|
|
46
|
-
const data = await response.json();
|
|
47
|
-
const latest = data.version;
|
|
48
|
-
return {
|
|
49
|
-
current,
|
|
50
|
-
latest,
|
|
51
|
-
updateAvailable: current !== latest,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
console.error("Failed to check for updates:", error);
|
|
56
|
-
return {
|
|
57
|
-
current,
|
|
58
|
-
latest: current,
|
|
59
|
-
updateAvailable: false,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
File without changes
|
|
File without changes
|