openbot 0.2.10 → 0.2.11
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/agents/topic-agent.js +17 -3
- package/dist/cli.js +1 -1
- package/dist/core/delegation.js +128 -22
- package/dist/core/manager.js +31 -8
- package/dist/core/plugins.js +5 -8
- package/dist/core/router.js +164 -13
- package/dist/open-bot.js +2 -2
- package/dist/plugins/approval/index.js +75 -162
- package/dist/plugins/file-system/index.js +2 -2
- package/dist/plugins/llm/context-budget.js +139 -0
- package/dist/plugins/llm/index.js +85 -31
- package/dist/plugins/memory/index.js +2 -2
- package/dist/plugins/shell/index.js +2 -2
- package/dist/plugins/skills/index.js +4 -4
- package/dist/registry/plugin-loader.js +81 -9
- package/dist/registry/plugin-registry.js +5 -5
- package/dist/server.js +0 -1
- package/dist/session.js +23 -5
- package/dist/ui/block.js +12 -0
- package/dist/ui/widgets/action-list.js +2 -9
- package/dist/ui/widgets/approval-card.js +9 -35
- package/dist/ui/widgets/code-snippet.js +2 -2
- package/dist/ui/widgets/data-block.js +2 -5
- package/dist/ui/widgets/data-table.js +2 -8
- package/dist/ui/widgets/empty-state.js +2 -7
- package/dist/ui/widgets/index.js +4 -0
- package/dist/ui/widgets/inquiry.js +7 -0
- package/dist/ui/widgets/key-value.js +2 -12
- package/dist/ui/widgets/progress-step.js +2 -5
- package/dist/ui/widgets/resource-card.js +2 -10
- package/dist/ui/widgets/status.js +2 -5
- package/dist/ui/widgets/todo-list.js +2 -0
- package/package.json +1 -2
|
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import { execSync } from "node:child_process";
|
|
5
5
|
import matter from "gray-matter";
|
|
6
|
+
import { z } from "zod";
|
|
6
7
|
import { PluginRegistry } from "./plugin-registry.js";
|
|
7
8
|
import { llmPlugin } from "../plugins/llm/index.js";
|
|
8
9
|
import { createModel } from "../models.js";
|
|
@@ -79,6 +80,32 @@ export async function ensurePluginReady(pluginDir) {
|
|
|
79
80
|
console.error(`[plugins] Failed to prepare plugin in ${pluginDir}:`, err);
|
|
80
81
|
}
|
|
81
82
|
}
|
|
83
|
+
// ── AGENT.md Config ──────────────────────────────────────────────────
|
|
84
|
+
function jsonToZod(schema) {
|
|
85
|
+
if (typeof schema === "string") {
|
|
86
|
+
if (schema === "string")
|
|
87
|
+
return z.string();
|
|
88
|
+
if (schema === "number")
|
|
89
|
+
return z.number();
|
|
90
|
+
if (schema === "boolean")
|
|
91
|
+
return z.boolean();
|
|
92
|
+
}
|
|
93
|
+
if (Array.isArray(schema)) {
|
|
94
|
+
// If it's a simple array like ["string"], take the first item
|
|
95
|
+
if (schema.length === 1)
|
|
96
|
+
return z.array(jsonToZod(schema[0]));
|
|
97
|
+
// For anything else, treat as array of any (or you could improve this)
|
|
98
|
+
return z.array(z.any());
|
|
99
|
+
}
|
|
100
|
+
if (typeof schema === "object" && schema !== null) {
|
|
101
|
+
const shape = {};
|
|
102
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
103
|
+
shape[key] = jsonToZod(value);
|
|
104
|
+
}
|
|
105
|
+
return z.object(shape);
|
|
106
|
+
}
|
|
107
|
+
return z.any();
|
|
108
|
+
}
|
|
82
109
|
export async function readAgentConfig(agentDir) {
|
|
83
110
|
const mdPath = path.join(agentDir, "AGENT.md");
|
|
84
111
|
let mdContent = "";
|
|
@@ -95,9 +122,11 @@ export async function readAgentConfig(agentDir) {
|
|
|
95
122
|
description: typeof config.description === "string" ? config.description : "",
|
|
96
123
|
model: config.model,
|
|
97
124
|
image: config.image,
|
|
125
|
+
base: config.base,
|
|
98
126
|
plugins: config.plugins || [],
|
|
99
127
|
instructions: parsed.content.trim() || "",
|
|
100
128
|
subscribe: config.subscribe,
|
|
129
|
+
outputSchema: config.outputSchema,
|
|
101
130
|
};
|
|
102
131
|
}
|
|
103
132
|
// ── Agent composition (declarative AGENT.md agents) ──────────────────
|
|
@@ -118,14 +147,48 @@ function composeAgentFromConfig(config, toolRegistry, model) {
|
|
|
118
147
|
Object.assign(allToolDefinitions, entry.toolDefinitions);
|
|
119
148
|
}
|
|
120
149
|
const plugin = (builder) => {
|
|
150
|
+
// 1. Initialize all regular tool plugins
|
|
121
151
|
for (const { plugin: toolPlugin, config: resolvedConfig } of pluginFactories) {
|
|
122
152
|
builder.use(toolPlugin({ ...resolvedConfig, model }));
|
|
123
153
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
})
|
|
154
|
+
// 2. Resolve the "Brain" (Base Plugin)
|
|
155
|
+
const baseInput = config.base || "llm";
|
|
156
|
+
const isBaseString = typeof baseInput === "string";
|
|
157
|
+
const baseName = isBaseString ? baseInput : baseInput.name;
|
|
158
|
+
const baseConfig = isBaseString ? {} : (baseInput.config || {});
|
|
159
|
+
const resolvedBaseConfig = resolveConfigPaths(baseConfig);
|
|
160
|
+
if (baseName === "llm") {
|
|
161
|
+
// Default built-in brain
|
|
162
|
+
builder.use(llmPlugin({
|
|
163
|
+
model,
|
|
164
|
+
system: config.instructions,
|
|
165
|
+
toolDefinitions: allToolDefinitions,
|
|
166
|
+
outputSchema: config.outputSchema ? jsonToZod(config.outputSchema) : undefined,
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Custom autonomous brain (e.g. codex)
|
|
171
|
+
const baseEntry = toolRegistry.get(baseName);
|
|
172
|
+
if (!baseEntry || baseEntry.type !== "tool") {
|
|
173
|
+
console.error(`[plugins] "${config.name}": base plugin "${baseName}" not found or invalid. Falling back to default LLM brain.`);
|
|
174
|
+
builder.use(llmPlugin({
|
|
175
|
+
model,
|
|
176
|
+
system: config.instructions,
|
|
177
|
+
toolDefinitions: allToolDefinitions,
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// Use the custom plugin as the autonomous engine.
|
|
182
|
+
// It must follow the Base Plugin contract (receive model, system, tools).
|
|
183
|
+
builder.use(baseEntry.plugin({
|
|
184
|
+
...resolvedBaseConfig,
|
|
185
|
+
model,
|
|
186
|
+
system: config.instructions,
|
|
187
|
+
toolDefinitions: allToolDefinitions,
|
|
188
|
+
outputSchema: config.outputSchema ? jsonToZod(config.outputSchema) : undefined,
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
129
192
|
};
|
|
130
193
|
return { plugin, toolDefinitions: allToolDefinitions };
|
|
131
194
|
}
|
|
@@ -149,6 +212,7 @@ async function loadToolPluginsFromDir(dir) {
|
|
|
149
212
|
const entryData = module.plugin || module.default || module.entry;
|
|
150
213
|
if (entryData && typeof entryData.factory === "function") {
|
|
151
214
|
plugins.push({
|
|
215
|
+
id: entry.name,
|
|
152
216
|
name: entryData.name || entry.name,
|
|
153
217
|
description: entryData.description || `Tool plugin ${entry.name}`,
|
|
154
218
|
type: "tool",
|
|
@@ -225,12 +289,14 @@ export async function discoverPlugins(dir, registry, defaultModel, options) {
|
|
|
225
289
|
if (codeAgentDef && typeof codeAgentDef.factory === "function") {
|
|
226
290
|
const meta = await getPluginMetadata(pluginDir);
|
|
227
291
|
const folderName = path.basename(pluginDir);
|
|
292
|
+
const id = folderName; // Folder name as slug
|
|
228
293
|
let name = codeAgentDef.name || meta.name;
|
|
229
294
|
if (!name || /^Unnamed\s+(Plugin|Tool|Agent)$/i.test(name)) {
|
|
230
295
|
name = toTitleCaseFromSlug(folderName);
|
|
231
296
|
}
|
|
232
297
|
const description = codeAgentDef.description || meta.description || "Code Agent";
|
|
233
298
|
registry.register({
|
|
299
|
+
id,
|
|
234
300
|
name,
|
|
235
301
|
description,
|
|
236
302
|
type: "agent",
|
|
@@ -239,16 +305,18 @@ export async function discoverPlugins(dir, registry, defaultModel, options) {
|
|
|
239
305
|
subscribe: codeAgentDef.subscribe,
|
|
240
306
|
folder: pluginDir,
|
|
241
307
|
});
|
|
242
|
-
console.log(`[plugins] Loaded code-only agent: ${name} — ${description}`);
|
|
308
|
+
console.log(`[plugins] Loaded code-only agent: ${id} (${name}) — ${description}`);
|
|
243
309
|
}
|
|
244
310
|
else if (entryData && typeof entryData.factory === "function") {
|
|
245
311
|
const meta = await getPluginMetadata(pluginDir);
|
|
246
312
|
const folderName = path.basename(pluginDir);
|
|
313
|
+
const id = folderName;
|
|
247
314
|
let name = entryData.name || meta.name;
|
|
248
315
|
if (!name || /^Unnamed\s+(Plugin|Tool|Agent)$/i.test(name)) {
|
|
249
316
|
name = toTitleCaseFromSlug(folderName);
|
|
250
317
|
}
|
|
251
318
|
const pluginEntry = {
|
|
319
|
+
id,
|
|
252
320
|
name,
|
|
253
321
|
description: entryData.description || meta.description || "Tool plugin",
|
|
254
322
|
type: "tool",
|
|
@@ -257,7 +325,7 @@ export async function discoverPlugins(dir, registry, defaultModel, options) {
|
|
|
257
325
|
folder: pluginDir,
|
|
258
326
|
};
|
|
259
327
|
registry.register(pluginEntry);
|
|
260
|
-
console.log(`[plugins] Loaded tool: ${pluginEntry.name}`);
|
|
328
|
+
console.log(`[plugins] Loaded tool: ${id} (${pluginEntry.name})`);
|
|
261
329
|
}
|
|
262
330
|
else {
|
|
263
331
|
console.warn(`[plugins] "${path.basename(pluginDir)}" does not export a valid plugin (missing factory)`);
|
|
@@ -282,12 +350,14 @@ export async function discoverPlugins(dir, registry, defaultModel, options) {
|
|
|
282
350
|
if (definition && typeof definition.factory === "function") {
|
|
283
351
|
const config = await readAgentConfig(agentDir);
|
|
284
352
|
const meta = await getPluginMetadata(agentDir);
|
|
353
|
+
const id = folderName;
|
|
285
354
|
let name = config.name || definition.name || meta.name;
|
|
286
355
|
if (!name || /^Unnamed\s+(Plugin|Tool|Agent)$/i.test(name)) {
|
|
287
356
|
name = toTitleCaseFromSlug(folderName);
|
|
288
357
|
}
|
|
289
358
|
const description = definition.description || config.description || "TS Agent";
|
|
290
359
|
registry.register({
|
|
360
|
+
id,
|
|
291
361
|
name,
|
|
292
362
|
description,
|
|
293
363
|
type: "agent",
|
|
@@ -296,13 +366,14 @@ export async function discoverPlugins(dir, registry, defaultModel, options) {
|
|
|
296
366
|
subscribe: definition.subscribe || config.subscribe,
|
|
297
367
|
folder: agentDir,
|
|
298
368
|
});
|
|
299
|
-
console.log(`[plugins] Loaded TS agent: ${name} — ${description}`);
|
|
369
|
+
console.log(`[plugins] Loaded TS agent: ${id} (${name}) — ${description}`);
|
|
300
370
|
}
|
|
301
371
|
}
|
|
302
372
|
else {
|
|
303
373
|
// Declarative Agent — AGENT.md only, auto-wrapped with llmPlugin.
|
|
304
374
|
const config = await readAgentConfig(agentDir);
|
|
305
375
|
const meta = await getPluginMetadata(agentDir);
|
|
376
|
+
const id = folderName;
|
|
306
377
|
let resolvedName = config.name || meta.name;
|
|
307
378
|
if (!resolvedName || /^Unnamed\s+(Plugin|Tool|Agent)$/i.test(resolvedName)) {
|
|
308
379
|
resolvedName = toTitleCaseFromSlug(folderName);
|
|
@@ -330,6 +401,7 @@ export async function discoverPlugins(dir, registry, defaultModel, options) {
|
|
|
330
401
|
}
|
|
331
402
|
const { plugin, toolDefinitions } = composeAgentFromConfig(config, scopedRegistry, agentModel);
|
|
332
403
|
registry.register({
|
|
404
|
+
id,
|
|
333
405
|
name: resolvedName,
|
|
334
406
|
description: resolvedDescription,
|
|
335
407
|
type: "agent",
|
|
@@ -338,7 +410,7 @@ export async function discoverPlugins(dir, registry, defaultModel, options) {
|
|
|
338
410
|
subscribe: config.subscribe,
|
|
339
411
|
folder: agentDir,
|
|
340
412
|
});
|
|
341
|
-
console.log(`[plugins] Loaded agent: ${resolvedName} — ${resolvedDescription}${config.model ? ` (model: ${config.model})` : ""}`);
|
|
413
|
+
console.log(`[plugins] Loaded agent: ${id} (${resolvedName}) — ${resolvedDescription}${config.model ? ` (model: ${config.model})` : ""}`);
|
|
342
414
|
}
|
|
343
415
|
}
|
|
344
416
|
catch (err) {
|
|
@@ -33,12 +33,12 @@ export class PluginRegistry {
|
|
|
33
33
|
getTools() {
|
|
34
34
|
return this.getAll().filter(p => p.type === "tool");
|
|
35
35
|
}
|
|
36
|
-
/** Returns agent
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
36
|
+
/** Returns agent IDs as a tuple suitable for z.enum(). */
|
|
37
|
+
getAgentIds() {
|
|
38
|
+
const ids = this.getAgents().map(a => a.id);
|
|
39
|
+
if (ids.length === 0) {
|
|
40
40
|
throw new Error("No agents registered — at least one agent is required");
|
|
41
41
|
}
|
|
42
|
-
return
|
|
42
|
+
return ids;
|
|
43
43
|
}
|
|
44
44
|
}
|
package/dist/server.js
CHANGED
|
@@ -882,7 +882,6 @@ export async function startServer(options = {}) {
|
|
|
882
882
|
console.log(`OpenBot server listening at http://localhost:${PORT}`);
|
|
883
883
|
console.log(` - Chat endpoint: POST /api/chat`);
|
|
884
884
|
console.log(` - REST endpoints: /api/config, /api/sessions, /api/agents`);
|
|
885
|
-
console.log(`\n🚀 TIP: Use 'openbot up' to run both the server and web dashboard together.`);
|
|
886
885
|
if (options.openaiApiKey)
|
|
887
886
|
console.log(" - Using OpenAI API Key from CLI");
|
|
888
887
|
if (options.anthropicApiKey)
|
package/dist/session.js
CHANGED
|
@@ -41,6 +41,24 @@ function getSessionDir(sessionId) {
|
|
|
41
41
|
* System messages at the start are always preserved and don't count toward the limit.
|
|
42
42
|
*/
|
|
43
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
|
+
}
|
|
44
62
|
export async function loadSession(sessionId) {
|
|
45
63
|
const sessionDir = getSessionDir(sessionId);
|
|
46
64
|
const statePath = path.join(sessionDir, "state.json");
|
|
@@ -125,8 +143,7 @@ export async function listSessions() {
|
|
|
125
143
|
const statePath = path.join(sessionPath, "state.json");
|
|
126
144
|
if (fs.existsSync(statePath)) {
|
|
127
145
|
const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
|
|
128
|
-
|
|
129
|
-
if ((state.messages && state.messages.length > 0) || state.title) {
|
|
146
|
+
if (hasPersistedContent(state)) {
|
|
130
147
|
sessions.push({
|
|
131
148
|
id: subItem,
|
|
132
149
|
mtime: fs.statSync(statePath).birthtime, // sort by creation time
|
|
@@ -141,8 +158,7 @@ export async function listSessions() {
|
|
|
141
158
|
const statePath = path.join(itemPath, "state.json");
|
|
142
159
|
if (fs.existsSync(statePath)) {
|
|
143
160
|
const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
|
|
144
|
-
|
|
145
|
-
if ((state.messages && state.messages.length > 0) || state.title) {
|
|
161
|
+
if (hasPersistedContent(state)) {
|
|
146
162
|
sessions.push({
|
|
147
163
|
id: item,
|
|
148
164
|
title: state.title ?? undefined,
|
|
@@ -157,5 +173,7 @@ export async function listSessions() {
|
|
|
157
173
|
catch (error) {
|
|
158
174
|
console.error("Failed to list sessions:", error);
|
|
159
175
|
}
|
|
160
|
-
return sessions
|
|
176
|
+
return sessions
|
|
177
|
+
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())
|
|
178
|
+
.slice(0, MAX_LISTED_SESSIONS);
|
|
161
179
|
}
|
package/dist/ui/block.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
});
|
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const actionList = (title, actions) =>
|
|
3
|
-
ui.col({ gap: 'md' }, [
|
|
4
|
-
ui.heading(title, { level: 4 }),
|
|
5
|
-
ui.row({ gap: 'sm', wrap: 'wrap' }, actions.map(a => ui.button({ variant: a.variant || 'outline', onClickAction: a.action }, [
|
|
6
|
-
ui.text(a.label, { size: 'sm' })
|
|
7
|
-
])))
|
|
8
|
-
])
|
|
9
|
-
]);
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const actionList = (title, actions) => block('action-list', { title, actions });
|
|
@@ -1,35 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const approvalCard = (title, data, approveAction, denyAction) =>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
ui.text(`${detail.label}:`, { size: 'xs', color: 'muted', weight: 'semibold' }),
|
|
11
|
-
ui.text(detail.value, { size: 'xs' }),
|
|
12
|
-
]))),
|
|
13
|
-
]),
|
|
14
|
-
]
|
|
15
|
-
: []),
|
|
16
|
-
...(data.rawPayload
|
|
17
|
-
? [
|
|
18
|
-
ui.box({ border: true, radius: 'sm', padding: 'sm' }, [
|
|
19
|
-
ui.col({ gap: 'xs' }, [
|
|
20
|
-
ui.text('Full action payload', { size: 'xs', color: 'muted', weight: 'semibold' }),
|
|
21
|
-
ui.text(data.rawPayload, { size: 'xs' }),
|
|
22
|
-
]),
|
|
23
|
-
]),
|
|
24
|
-
]
|
|
25
|
-
: []),
|
|
26
|
-
ui.row({ gap: 'sm', justify: 'end' }, [
|
|
27
|
-
ui.button({ variant: 'outline', onClickAction: denyAction }, [
|
|
28
|
-
ui.text('Deny', { size: 'xs' })
|
|
29
|
-
]),
|
|
30
|
-
ui.button({ variant: 'primary', onClickAction: approveAction }, [
|
|
31
|
-
ui.text('Approve', { size: 'xs' })
|
|
32
|
-
])
|
|
33
|
-
])
|
|
34
|
-
])
|
|
35
|
-
]);
|
|
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,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const codeSnippet = (code, language = 'text') =>
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const codeSnippet = (code, language = 'text') => block('code-snippet', { code, language });
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const dataBlockWidget = (data) =>
|
|
3
|
-
ui.text(`${key}:`, { weight: 'semibold', size: 'xs', color: 'muted' }),
|
|
4
|
-
ui.text(String(value), { size: 'xs' }),
|
|
5
|
-
])));
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const dataBlockWidget = (data) => block('data-block', { data });
|
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const dataTable = (headers, rows) => {
|
|
3
|
-
const headerRow = `| ${headers.join(' | ')} |`;
|
|
4
|
-
const separator = `| ${headers.map(() => '---').join(' | ')} |`;
|
|
5
|
-
const dataRows = rows.map(row => `| ${row.join(' | ')} |`).join('\n');
|
|
6
|
-
const markdownTable = `${headerRow}\n${separator}\n${dataRows}`;
|
|
7
|
-
return ui.markdown(markdownTable);
|
|
8
|
-
};
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const dataTable = (headers, rows) => block('data-table', { headers, rows });
|
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const emptyState = (message, iconName) =>
|
|
3
|
-
ui.col({ align: 'center', justify: 'center', gap: 'sm' }, [
|
|
4
|
-
iconName ? ui.icon(iconName) : ui.text('∅', { size: 'lg', color: 'muted' }),
|
|
5
|
-
ui.text(message, { size: 'sm', color: 'muted' })
|
|
6
|
-
])
|
|
7
|
-
]);
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const emptyState = (message, iconName) => block('empty-state', { message, iconName });
|
package/dist/ui/widgets/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import { progressStep } from './progress-step.js';
|
|
|
6
6
|
import { approvalCard } from './approval-card.js';
|
|
7
7
|
import { actionList } from './action-list.js';
|
|
8
8
|
import { emptyState } from './empty-state.js';
|
|
9
|
+
import { todoList } from './todo-list.js';
|
|
10
|
+
import { inquiryCard } from './inquiry.js';
|
|
9
11
|
export const widgets = {
|
|
10
12
|
keyValue,
|
|
11
13
|
dataTable,
|
|
@@ -15,5 +17,7 @@ export const widgets = {
|
|
|
15
17
|
approvalCard,
|
|
16
18
|
actionList,
|
|
17
19
|
emptyState,
|
|
20
|
+
todoList,
|
|
21
|
+
inquiryCard,
|
|
18
22
|
};
|
|
19
23
|
export default widgets;
|
|
@@ -1,12 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const keyValue = (title, data) =>
|
|
3
|
-
ui.col({ gap: 'md' }, [
|
|
4
|
-
ui.heading(title, { level: 4 }),
|
|
5
|
-
ui.col({ gap: 'xs' }, Object.entries(data)
|
|
6
|
-
.filter(([_, v]) => v !== undefined && v !== null)
|
|
7
|
-
.map(([key, value]) => ui.row({ gap: 'sm', align: 'start' }, [
|
|
8
|
-
ui.text(`${key}:`, { weight: 'bold', size: 'sm', color: 'muted' }),
|
|
9
|
-
ui.text(String(value), { size: 'sm' })
|
|
10
|
-
])))
|
|
11
|
-
])
|
|
12
|
-
]);
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const keyValue = (title, data) => block('key-value', { title, data });
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const progressStep = (currentStep, totalSteps, label) =>
|
|
3
|
-
ui.text(`Step ${currentStep} of ${totalSteps}`, { weight: 'bold', size: 'sm' }),
|
|
4
|
-
ui.text(label, { size: 'sm', color: 'muted' })
|
|
5
|
-
]);
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const progressStep = (currentStep, totalSteps, label) => block('progress-step', { currentStep, totalSteps, label });
|
|
@@ -1,10 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const resourceCardWidget = (title, subtitle, children = []) =>
|
|
3
|
-
border: true,
|
|
4
|
-
radius: 'lg',
|
|
5
|
-
padding: 'md',
|
|
6
|
-
}, [
|
|
7
|
-
ui.heading(title, { level: 4 }),
|
|
8
|
-
ui.text(subtitle ?? '', { size: 'sm', color: 'mutedForeground' }),
|
|
9
|
-
...children,
|
|
10
|
-
]);
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const resourceCardWidget = (title, subtitle, children = []) => block('resource-card', { title, subtitle, children });
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export const statusWidget = (message, severity = 'info') =>
|
|
3
|
-
color: severity === 'error' ? 'danger' : severity === 'success' ? 'success' : 'muted',
|
|
4
|
-
size: 'xs',
|
|
5
|
-
});
|
|
1
|
+
import { block } from '../block.js';
|
|
2
|
+
export const statusWidget = (message, severity = 'info', options = {}) => block('status', { message, severity }, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openbot",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@ai-sdk/anthropic": "^3.0.33",
|
|
14
14
|
"@ai-sdk/openai": "^3.0.13",
|
|
15
|
-
"@melony/ui-kit": "^0.1.30",
|
|
16
15
|
"@types/cors": "^2.8.19",
|
|
17
16
|
"ai": "^6.0.42",
|
|
18
17
|
"commander": "^14.0.2",
|