@meetopenbot/openbot 0.1.1
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/cloud-mode.d.ts +5 -0
- package/dist/cloud-mode.js +4 -0
- package/dist/context.d.ts +11 -0
- package/dist/context.js +120 -0
- package/dist/history.d.ts +9 -0
- package/dist/history.js +145 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +77 -0
- package/dist/model.d.ts +2 -0
- package/dist/model.js +20 -0
- package/dist/runtime.d.ts +25 -0
- package/dist/runtime.js +401 -0
- package/dist/system-prompt.d.ts +1 -0
- package/dist/system-prompt.js +57 -0
- package/dist/tools/approval.d.ts +3 -0
- package/dist/tools/approval.js +130 -0
- package/dist/tools/bash.d.ts +3 -0
- package/dist/tools/bash.js +425 -0
- package/dist/tools/delegation.d.ts +3 -0
- package/dist/tools/delegation.js +130 -0
- package/dist/tools/memory.d.ts +3 -0
- package/dist/tools/memory.js +163 -0
- package/dist/tools/preview.d.ts +4 -0
- package/dist/tools/preview.js +269 -0
- package/dist/tools/storage.d.ts +57 -0
- package/dist/tools/storage.js +335 -0
- package/dist/tools/todo-service.d.ts +28 -0
- package/dist/tools/todo-service.js +93 -0
- package/dist/tools/todo.d.ts +3 -0
- package/dist/tools/todo.js +146 -0
- package/dist/tools/ui.d.ts +9 -0
- package/dist/tools/ui.js +120 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.js +12 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.js +12 -0
- package/dist/utils/workspace-url.d.ts +5 -0
- package/dist/utils/workspace-url.js +6 -0
- package/package.json +32 -0
package/dist/tools/ui.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* `ui` — provides a tool for the agent to render interactive UI widgets.
|
|
5
|
+
*
|
|
6
|
+
* The model can choose which widget to render (form, choice, list, message)
|
|
7
|
+
* depending on the situation.
|
|
8
|
+
*/
|
|
9
|
+
export const uiPlugin = {
|
|
10
|
+
id: 'ui',
|
|
11
|
+
name: 'UI',
|
|
12
|
+
description: 'Render interactive UI widgets to interact with the user.',
|
|
13
|
+
toolDefinitions: {
|
|
14
|
+
render_widget: {
|
|
15
|
+
description: 'Render a UI widget to the user. Use "form" for data collection, "choice" for simple selection, "list" for displaying items, and "message" for simple notifications with actions. When using form widge to unquire user, do not provide complex forms with many fields, always try to make it simple to keep the experience smooth and straightforward.',
|
|
16
|
+
inputSchema: z.object({
|
|
17
|
+
kind: z.enum(['message', 'choice', 'form', 'list']).describe('The type of widget to render.'),
|
|
18
|
+
title: z.string().describe('The title of the widget.'),
|
|
19
|
+
description: z.string().optional().describe('A description or body text.'),
|
|
20
|
+
fields: z.array(z.object({
|
|
21
|
+
id: z.string().describe('Unique ID for the field.'),
|
|
22
|
+
label: z.string().describe('Label shown to the user.'),
|
|
23
|
+
type: z.enum(['text', 'textarea', 'number', 'boolean', 'select', 'multiselect', 'date']),
|
|
24
|
+
description: z.string().optional(),
|
|
25
|
+
placeholder: z.string().optional(),
|
|
26
|
+
required: z.boolean().optional(),
|
|
27
|
+
options: z.array(z.object({ label: z.string(), value: z.string() })).optional(),
|
|
28
|
+
defaultValue: z.any().optional()
|
|
29
|
+
})).optional().describe('Required for kind="form". List of form fields.'),
|
|
30
|
+
actions: z.array(z.object({
|
|
31
|
+
id: z.string(),
|
|
32
|
+
label: z.string(),
|
|
33
|
+
variant: z.enum(['primary', 'secondary', 'danger']).optional(),
|
|
34
|
+
})).optional().describe('Buttons or actions available on the widget.'),
|
|
35
|
+
items: z.array(z.object({
|
|
36
|
+
id: z.string(),
|
|
37
|
+
label: z.string(),
|
|
38
|
+
description: z.string().optional(),
|
|
39
|
+
status: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Status label shown on the item (e.g. "Pending", "Shipped").'),
|
|
43
|
+
statusVariant: z
|
|
44
|
+
.enum(['default', 'success', 'warning', 'danger', 'info'])
|
|
45
|
+
.optional()
|
|
46
|
+
.describe('Semantic hint for status badge coloring in the client.'),
|
|
47
|
+
metadata: z.record(z.string(), z.any()).optional()
|
|
48
|
+
})).optional().describe('Required for kind="list". List of items to display.'),
|
|
49
|
+
submitLabel: z.string().optional().describe('Label for the primary action button (e.g. "Submit", "Save").')
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
factory: () => (builder) => {
|
|
54
|
+
// Handle the tool call from the agent
|
|
55
|
+
builder.on('action:render_widget', async function* (event, context) {
|
|
56
|
+
const widgetEvent = event;
|
|
57
|
+
const toolCallId = widgetEvent.meta?.toolCallId;
|
|
58
|
+
const threadId = widgetEvent.meta?.threadId || context.state.threadId;
|
|
59
|
+
if (!toolCallId)
|
|
60
|
+
return;
|
|
61
|
+
const widgetId = randomUUID();
|
|
62
|
+
// Emit the UI widget event to the client
|
|
63
|
+
yield {
|
|
64
|
+
type: 'client:ui:widget',
|
|
65
|
+
data: {
|
|
66
|
+
...widgetEvent.data,
|
|
67
|
+
widgetId,
|
|
68
|
+
metadata: {
|
|
69
|
+
type: 'ui:request',
|
|
70
|
+
originalEvent: widgetEvent
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
meta: { agentId: context.state.agentId, threadId }
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
// Handle the user's response from the UI widget
|
|
77
|
+
builder.on('client:ui:widget:response', async function* (event, context) {
|
|
78
|
+
const responseEvent = event;
|
|
79
|
+
const { widgetId, actionId, values, metadata } = responseEvent.data;
|
|
80
|
+
if (metadata?.type !== 'ui:request')
|
|
81
|
+
return;
|
|
82
|
+
const originalEvent = metadata.originalEvent;
|
|
83
|
+
const toolCallId = originalEvent?.meta?.toolCallId;
|
|
84
|
+
const threadId = originalEvent?.meta?.threadId || context.state.threadId;
|
|
85
|
+
if (!toolCallId)
|
|
86
|
+
return;
|
|
87
|
+
// Yield a "submitted" widget update to the UI to collapse/disable it
|
|
88
|
+
yield {
|
|
89
|
+
type: 'client:ui:widget',
|
|
90
|
+
data: {
|
|
91
|
+
widgetId,
|
|
92
|
+
title: originalEvent.data.title,
|
|
93
|
+
kind: originalEvent.data.kind,
|
|
94
|
+
state: 'submitted',
|
|
95
|
+
body: "Thank you for your response. We will process it and get back to you soon.",
|
|
96
|
+
display: 'collapsed',
|
|
97
|
+
disabled: true,
|
|
98
|
+
actions: [], // Clear actions to disable buttons in UI
|
|
99
|
+
},
|
|
100
|
+
meta: { agentId: context.state.agentId, threadId },
|
|
101
|
+
};
|
|
102
|
+
// Emit the tool result event so the agent runtime can resume
|
|
103
|
+
yield {
|
|
104
|
+
type: 'action:render_widget:result',
|
|
105
|
+
data: {
|
|
106
|
+
success: true,
|
|
107
|
+
actionId,
|
|
108
|
+
values,
|
|
109
|
+
output: JSON.stringify(values)
|
|
110
|
+
},
|
|
111
|
+
meta: {
|
|
112
|
+
agentId: context.state.agentId,
|
|
113
|
+
threadId,
|
|
114
|
+
toolCallId
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
export default uiPlugin;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Plugin as SdkPlugin, PluginContext as SdkPluginContext, OpenBotState as SdkOpenBotState, ToolActionEvent, PluginFactory as SdkPluginFactory, PluginBuilder, PluginHandlerContext, OpenBotEvent } from '@meetopenbot/plugin-sdk';
|
|
2
|
+
export { definePlugin } from '@meetopenbot/plugin-sdk';
|
|
3
|
+
export type { AgentInvokeEvent, AgentOutputEvent, ConfigSchema, OpenBotEvent, PluginBuilder, PluginFactory, PluginHandlerContext, Storage, ToolDefinition, ToolActionEvent, UIWidgetListItem, UIWidgetResponseEvent, } from '@meetopenbot/plugin-sdk';
|
|
4
|
+
export type MemoryScopeAlias = 'global' | 'agent' | 'channel';
|
|
5
|
+
export type DelegateTaskEvent = ToolActionEvent<{
|
|
6
|
+
agentId: string;
|
|
7
|
+
prompt: string;
|
|
8
|
+
}> & {
|
|
9
|
+
type: 'action:delegate_task';
|
|
10
|
+
};
|
|
11
|
+
export type RenderWidgetEvent = ToolActionEvent<Record<string, unknown>> & {
|
|
12
|
+
type: 'action:render_widget';
|
|
13
|
+
};
|
|
14
|
+
/** Runtime state extends the SDK with fields used by the OpenBot agent plugin. */
|
|
15
|
+
export type OpenBotState = SdkOpenBotState & {
|
|
16
|
+
model?: string;
|
|
17
|
+
currentUser?: {
|
|
18
|
+
userName?: string;
|
|
19
|
+
};
|
|
20
|
+
pendingToolCallIds?: string[];
|
|
21
|
+
threadDetails?: SdkOpenBotState['threadDetails'] & {
|
|
22
|
+
name?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Builder surface for registering `action:*` handlers.
|
|
27
|
+
* SDK `OpenBotEvent` includes a `type: string` fallback that prevents Melony from
|
|
28
|
+
* narrowing specific action events; this helper keeps handlers type-safe.
|
|
29
|
+
*/
|
|
30
|
+
export type ActionBuilder = {
|
|
31
|
+
on<TData = Record<string, unknown>>(action: string, handler: (event: ToolActionEvent<TData>, context: PluginHandlerContext) => AsyncGenerator<OpenBotEvent> | void): void;
|
|
32
|
+
};
|
|
33
|
+
export declare function asActionBuilder(builder: PluginBuilder): ActionBuilder;
|
|
34
|
+
export interface PluginHost {
|
|
35
|
+
runAgent: (options: {
|
|
36
|
+
runId: string;
|
|
37
|
+
agentId: string;
|
|
38
|
+
event: OpenBotEvent;
|
|
39
|
+
channelId: string;
|
|
40
|
+
threadId?: string;
|
|
41
|
+
persistEvents?: boolean;
|
|
42
|
+
publicBaseUrl?: string;
|
|
43
|
+
onEvent: (event: OpenBotEvent, state?: OpenBotState) => Promise<void>;
|
|
44
|
+
}) => Promise<void>;
|
|
45
|
+
isCloudSystemAgent: (agentId: string) => boolean;
|
|
46
|
+
isCloudMode: () => boolean;
|
|
47
|
+
parseOpenbotAuthMode: (value: unknown) => 'credits' | 'byok';
|
|
48
|
+
resolveModelRegistry: () => Promise<{
|
|
49
|
+
providers?: Record<string, {
|
|
50
|
+
label: string;
|
|
51
|
+
models: Array<{
|
|
52
|
+
id: string;
|
|
53
|
+
label: string;
|
|
54
|
+
description: string;
|
|
55
|
+
}>;
|
|
56
|
+
}>;
|
|
57
|
+
}>;
|
|
58
|
+
listApiKeyProvidersFromRegistry: (registry: Awaited<ReturnType<PluginHost['resolveModelRegistry']>>) => Array<{
|
|
59
|
+
id: string;
|
|
60
|
+
label: string;
|
|
61
|
+
}>;
|
|
62
|
+
saveConfig: (patch: Record<string, unknown>) => void;
|
|
63
|
+
getBaseDir: () => string;
|
|
64
|
+
resolvePath: (p: string) => string;
|
|
65
|
+
orchestratorAgentId: string;
|
|
66
|
+
openbotPluginId: string;
|
|
67
|
+
defaultCloudAuthMode: 'credits' | 'byok';
|
|
68
|
+
}
|
|
69
|
+
/** Host context extends the SDK with OpenBot runtime wiring. */
|
|
70
|
+
export interface PluginContext extends SdkPluginContext {
|
|
71
|
+
publicBaseUrl: string;
|
|
72
|
+
abortSignal?: AbortSignal;
|
|
73
|
+
host: PluginHost;
|
|
74
|
+
}
|
|
75
|
+
export interface Plugin extends Omit<SdkPlugin, 'factory' | 'configSchema'> {
|
|
76
|
+
configSchema?: SdkPlugin['configSchema'] | Record<string, unknown>;
|
|
77
|
+
factory: (context: PluginContext) => SdkPluginFactory;
|
|
78
|
+
}
|
|
79
|
+
/** Type-safe plugin definition for the extended OpenBot host context. */
|
|
80
|
+
export declare function defineOpenbotPlugin<T extends Plugin>(definition: T): T;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { definePlugin } from '@meetopenbot/plugin-sdk';
|
|
2
|
+
export function asActionBuilder(builder) {
|
|
3
|
+
return {
|
|
4
|
+
on(action, handler) {
|
|
5
|
+
builder.on(`action:${action}`, handler);
|
|
6
|
+
},
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/** Type-safe plugin definition for the extended OpenBot host context. */
|
|
10
|
+
export function defineOpenbotPlugin(definition) {
|
|
11
|
+
return definition;
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
export const DEFAULT_CHANNELS_DIR = 'channels';
|
|
4
|
+
export function resolvePath(p) {
|
|
5
|
+
return p.startsWith('~/') ? path.join(os.homedir(), p.slice(2)) : path.resolve(p);
|
|
6
|
+
}
|
|
7
|
+
export function getBaseDir() {
|
|
8
|
+
const env = process.env.OPENBOT_BASE_DIR?.trim();
|
|
9
|
+
if (env)
|
|
10
|
+
return resolvePath(env);
|
|
11
|
+
return path.join(os.homedir(), '.openbot');
|
|
12
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export function buildWorkspaceFileUrl(args) {
|
|
2
|
+
const base = args.baseUrl.replace(/\/$/, '');
|
|
3
|
+
const data = encodeURIComponent(JSON.stringify({ path: args.filePath }));
|
|
4
|
+
const channelId = encodeURIComponent(args.channelId);
|
|
5
|
+
return `${base}/api/state?channelId=${channelId}&type=${encodeURIComponent('action:storage:serve-file')}&data=${data}`;
|
|
6
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meetopenbot/openbot",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Monolithic OpenBot agent runtime with batteries-included tools.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@ai-sdk/anthropic": "^3.0.33",
|
|
22
|
+
"@ai-sdk/google": "^3.0.82",
|
|
23
|
+
"@ai-sdk/openai": "^3.0.13",
|
|
24
|
+
"@meetopenbot/plugin-sdk": "^0.1.5",
|
|
25
|
+
"ai": "^6.0.42",
|
|
26
|
+
"zod": "^4.3.5"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^20.10.1",
|
|
30
|
+
"typescript": "^5.9.3"
|
|
31
|
+
}
|
|
32
|
+
}
|