@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
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type OpenbotAuthMode = 'credits' | 'byok';
|
|
2
|
+
/** True when this runtime is a platform-managed cloud deployment. */
|
|
3
|
+
export declare const isCloudMode: () => boolean;
|
|
4
|
+
/** Default auth mode: Credits on cloud, BYOK locally. */
|
|
5
|
+
export declare const defaultAuthMode: () => OpenbotAuthMode;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** True when this runtime is a platform-managed cloud deployment. */
|
|
2
|
+
export const isCloudMode = () => process.env.OPENBOT_CLOUD_MODE === '1';
|
|
3
|
+
/** Default auth mode: Credits on cloud, BYOK locally. */
|
|
4
|
+
export const defaultAuthMode = () => (isCloudMode() ? 'credits' : 'byok');
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { OpenBotState } from './types.js';
|
|
2
|
+
export declare const DEFAULT_CONTEXT_BUDGET = 8000;
|
|
3
|
+
export declare const MAX_CONTEXT_FILES = 50;
|
|
4
|
+
/**
|
|
5
|
+
* Returns the known context window budget (in tokens) for a given model string.
|
|
6
|
+
*/
|
|
7
|
+
export declare const getContextBudgetForModel: (modelString: string) => number;
|
|
8
|
+
/**
|
|
9
|
+
* Simplified context builder for MVP.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildContext(state: OpenBotState, storage?: Record<string, any>): Promise<string>;
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { OPENBOT_SYSTEM_PROMPT } from './system-prompt.js';
|
|
2
|
+
import { todoService } from './tools/todo-service.js';
|
|
3
|
+
export const DEFAULT_CONTEXT_BUDGET = 8000;
|
|
4
|
+
export const MAX_CONTEXT_FILES = 50;
|
|
5
|
+
/**
|
|
6
|
+
* Returns the known context window budget (in tokens) for a given model string.
|
|
7
|
+
*/
|
|
8
|
+
export const getContextBudgetForModel = (modelString) => {
|
|
9
|
+
const budgets = {
|
|
10
|
+
'openai/gpt-4o': 128000,
|
|
11
|
+
'openai/gpt-4o-mini': 128000,
|
|
12
|
+
'openai/o1-preview': 128000,
|
|
13
|
+
'openai/o1-mini': 128000,
|
|
14
|
+
'anthropic/claude-3-5-sonnet-20240620': 200000,
|
|
15
|
+
'anthropic/claude-3-5-sonnet-latest': 200000,
|
|
16
|
+
'anthropic/claude-3-opus-20240229': 200000,
|
|
17
|
+
'anthropic/claude-3-sonnet-20240229': 200000,
|
|
18
|
+
'anthropic/claude-3-haiku-20240307': 200000,
|
|
19
|
+
};
|
|
20
|
+
return budgets[modelString] || DEFAULT_CONTEXT_BUDGET;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Simplified context builder for MVP.
|
|
24
|
+
*/
|
|
25
|
+
export async function buildContext(state, storage) {
|
|
26
|
+
const { channelId, threadId, channelDetails, agentId, threadDetails, agentDetails } = state;
|
|
27
|
+
const sections = [];
|
|
28
|
+
// Fetch agents once if storage is available
|
|
29
|
+
const allAgents = storage?.getAgents ? await storage.getAgents().catch(() => []) : [];
|
|
30
|
+
// 1. User
|
|
31
|
+
if (state.currentUser?.userName) {
|
|
32
|
+
sections.push(`## HUMAN\n- Name: ${state.currentUser.userName}`);
|
|
33
|
+
}
|
|
34
|
+
// 2. Environment
|
|
35
|
+
let env = '## ENVIRONMENT\n';
|
|
36
|
+
const channelName = channelDetails?.name || channelId;
|
|
37
|
+
env += `- Mode: Channel (#${channelName})\n`;
|
|
38
|
+
if (channelDetails?.cwd) {
|
|
39
|
+
env += `- Workspace: ${channelDetails.cwd}\n`;
|
|
40
|
+
}
|
|
41
|
+
if (threadId) {
|
|
42
|
+
env += `- Thread: ${threadDetails?.name || threadId}\n`;
|
|
43
|
+
}
|
|
44
|
+
sections.push(env);
|
|
45
|
+
// 2.5 Thread todos
|
|
46
|
+
if (channelId && threadId) {
|
|
47
|
+
try {
|
|
48
|
+
const list = await todoService.getTodos({ channelId, threadId });
|
|
49
|
+
if (list.items.length > 0) {
|
|
50
|
+
const formatted = list.items
|
|
51
|
+
.map((t) => `- [${t.status}] (${t.id}) ${t.content}`)
|
|
52
|
+
.join('\n');
|
|
53
|
+
sections.push(`## TODOS\n${formatted}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.warn('[context] Failed to fetch todos:', error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 2.6 Installed Agents
|
|
61
|
+
if (allAgents.length > 0) {
|
|
62
|
+
const formatted = allAgents
|
|
63
|
+
.map((a) => `- ${a.id}: ${a.name}${a.description ? ` - ${a.description}` : ''}`)
|
|
64
|
+
.join('\n');
|
|
65
|
+
sections.push(`## INSTALLED AGENTS\n${formatted}`);
|
|
66
|
+
}
|
|
67
|
+
// 3. Channel Spec
|
|
68
|
+
const spec = channelDetails?.spec?.trim();
|
|
69
|
+
if (spec) {
|
|
70
|
+
sections.push(`## CHANNEL SPECIFICATION\n${spec}`);
|
|
71
|
+
}
|
|
72
|
+
// 4. Files
|
|
73
|
+
if (storage?.listFiles && channelId && channelDetails?.cwd) {
|
|
74
|
+
try {
|
|
75
|
+
const files = await storage.listFiles({ channelId });
|
|
76
|
+
if (files.length > 0) {
|
|
77
|
+
const limited = files.slice(0, MAX_CONTEXT_FILES);
|
|
78
|
+
const formatted = limited
|
|
79
|
+
.map((f) => `- ${f.name}${f.isDirectory ? '/' : ''}`)
|
|
80
|
+
.join('\n');
|
|
81
|
+
let fileSection = `## FILES\n${formatted}`;
|
|
82
|
+
if (files.length > MAX_CONTEXT_FILES) {
|
|
83
|
+
fileSection += `\n- ... and ${files.length - MAX_CONTEXT_FILES} more files`;
|
|
84
|
+
}
|
|
85
|
+
sections.push(fileSection);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
sections.push('## FILES\n- (No files in workspace)');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.warn('[context] Failed to fetch files:', error);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// 5. Agent Instructions
|
|
96
|
+
const rawInstructions = agentDetails?.instructions?.trim();
|
|
97
|
+
if (rawInstructions &&
|
|
98
|
+
rawInstructions !== OPENBOT_SYSTEM_PROMPT.trim()) {
|
|
99
|
+
sections.push(`## Instructions\n${rawInstructions}`);
|
|
100
|
+
}
|
|
101
|
+
// 6. Memories
|
|
102
|
+
if (storage?.listMemories) {
|
|
103
|
+
try {
|
|
104
|
+
const scopes = ['global', `agent:${agentId}`];
|
|
105
|
+
if (channelId)
|
|
106
|
+
scopes.push(`channel:${channelId}`);
|
|
107
|
+
const records = await storage.listMemories({ scopes, limit: 20 });
|
|
108
|
+
if (records.length > 0) {
|
|
109
|
+
const formatted = records
|
|
110
|
+
.map((r) => `- (${r.scope}) ${r.content}`)
|
|
111
|
+
.join('\n');
|
|
112
|
+
sections.push(`## MEMORIES\n${formatted}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.warn('[context] Failed to fetch memories:', error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return sections.join('\n\n');
|
|
120
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OpenBotEvent } from './types.js';
|
|
2
|
+
import { type ModelMessage } from 'ai';
|
|
3
|
+
/**
|
|
4
|
+
* Converts a raw event log into a valid chain of ModelMessages for the AI SDK.
|
|
5
|
+
*
|
|
6
|
+
* This is a basic implementation that maps events to messages and filters out
|
|
7
|
+
* events from sub-processes (delegation) to avoid duplication in history.
|
|
8
|
+
*/
|
|
9
|
+
export declare function eventsToModelMessages(events: OpenBotEvent[]): ModelMessage[];
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures every tool-call has a matching tool-result before calling the LLM.
|
|
3
|
+
* Orphaned calls (interrupted run, missing :result event, etc.) get an empty
|
|
4
|
+
* result so the conversation can resume instead of failing validation.
|
|
5
|
+
*/
|
|
6
|
+
function fillMissingToolResults(messages) {
|
|
7
|
+
const filled = [];
|
|
8
|
+
const pending = new Map();
|
|
9
|
+
const flushPending = () => {
|
|
10
|
+
if (pending.size === 0)
|
|
11
|
+
return;
|
|
12
|
+
filled.push({
|
|
13
|
+
role: 'tool',
|
|
14
|
+
content: [...pending.entries()].map(([toolCallId, toolName]) => ({
|
|
15
|
+
type: 'tool-result',
|
|
16
|
+
toolCallId,
|
|
17
|
+
toolName,
|
|
18
|
+
output: { type: 'text', value: '' },
|
|
19
|
+
})),
|
|
20
|
+
});
|
|
21
|
+
pending.clear();
|
|
22
|
+
};
|
|
23
|
+
for (const message of messages) {
|
|
24
|
+
if (message.role === 'tool' && Array.isArray(message.content)) {
|
|
25
|
+
filled.push(message);
|
|
26
|
+
for (const part of message.content) {
|
|
27
|
+
if (part.type === 'tool-result') {
|
|
28
|
+
pending.delete(part.toolCallId);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
flushPending();
|
|
34
|
+
filled.push(message);
|
|
35
|
+
if (message.role === 'assistant' && Array.isArray(message.content)) {
|
|
36
|
+
for (const part of message.content) {
|
|
37
|
+
if (part.type === 'tool-call') {
|
|
38
|
+
const toolCall = part;
|
|
39
|
+
pending.set(toolCall.toolCallId, toolCall.toolName);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
flushPending();
|
|
45
|
+
return filled;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Converts a raw event log into a valid chain of ModelMessages for the AI SDK.
|
|
49
|
+
*
|
|
50
|
+
* This is a basic implementation that maps events to messages and filters out
|
|
51
|
+
* events from sub-processes (delegation) to avoid duplication in history.
|
|
52
|
+
*/
|
|
53
|
+
export function eventsToModelMessages(events) {
|
|
54
|
+
const messages = [];
|
|
55
|
+
for (const event of events) {
|
|
56
|
+
// Skip events that belong to a sub-process (like delegation)
|
|
57
|
+
// so they don't pollute the main conversation history.
|
|
58
|
+
if (event.meta?.parentToolCallId) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
switch (event.type) {
|
|
62
|
+
case 'agent:output': {
|
|
63
|
+
const content = event.data.content;
|
|
64
|
+
const last = messages[messages.length - 1];
|
|
65
|
+
if (last && last.role === 'assistant' && typeof last.content === 'string') {
|
|
66
|
+
last.content += content;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
messages.push({ role: 'assistant', content });
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case 'agent:invoke': {
|
|
74
|
+
const invokeEvent = event;
|
|
75
|
+
if (invokeEvent.data?.content && invokeEvent.data?.role) {
|
|
76
|
+
messages.push({
|
|
77
|
+
role: invokeEvent.data.role,
|
|
78
|
+
content: invokeEvent.data.content
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
default:
|
|
84
|
+
// Handle tool calls (action:*)
|
|
85
|
+
if (event.type.startsWith('action:') && !event.type.endsWith(':result')) {
|
|
86
|
+
const toolName = event.type.slice(7);
|
|
87
|
+
const toolCallId = event.meta?.toolCallId;
|
|
88
|
+
if (typeof toolCallId !== 'string')
|
|
89
|
+
break;
|
|
90
|
+
const toolCall = {
|
|
91
|
+
type: 'tool-call',
|
|
92
|
+
toolCallId,
|
|
93
|
+
toolName,
|
|
94
|
+
input: event.data,
|
|
95
|
+
};
|
|
96
|
+
const last = messages[messages.length - 1];
|
|
97
|
+
if (last && last.role === 'assistant') {
|
|
98
|
+
if (typeof last.content === 'string') {
|
|
99
|
+
last.content = [
|
|
100
|
+
{ type: 'text', text: last.content },
|
|
101
|
+
toolCall,
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
else if (Array.isArray(last.content)) {
|
|
105
|
+
last.content.push(toolCall);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
messages.push({
|
|
110
|
+
role: 'assistant',
|
|
111
|
+
content: [toolCall],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Handle tool results (action:*:result)
|
|
116
|
+
else if (event.type.startsWith('action:') && event.type.endsWith(':result')) {
|
|
117
|
+
const toolName = event.type.slice(7, -7);
|
|
118
|
+
const toolCallId = event.meta?.toolCallId;
|
|
119
|
+
if (typeof toolCallId !== 'string')
|
|
120
|
+
break;
|
|
121
|
+
const toolResult = {
|
|
122
|
+
type: 'tool-result',
|
|
123
|
+
toolCallId,
|
|
124
|
+
toolName,
|
|
125
|
+
output: {
|
|
126
|
+
type: 'text',
|
|
127
|
+
value: event?.data?.output || "No output", // ?.output is from delegation result
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
const last = messages[messages.length - 1];
|
|
131
|
+
if (last && last.role === 'tool' && Array.isArray(last.content)) {
|
|
132
|
+
last.content.push(toolResult);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
messages.push({
|
|
136
|
+
role: 'tool',
|
|
137
|
+
content: [toolResult],
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return fillMissingToolResults(messages);
|
|
145
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export declare const OPENBOT_PLUGIN_ID = "@meetopenbot/openbot";
|
|
2
|
+
/**
|
|
3
|
+
* `@meetopenbot/openbot` — the standard, opinionated OpenBot agent runtime.
|
|
4
|
+
*
|
|
5
|
+
* Batteries-included: shell, memory, todo, storage tools, delegation, approval,
|
|
6
|
+
* preview, and the LLM loop.
|
|
7
|
+
*/
|
|
8
|
+
export declare const openbotPlugin: {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
configSchema: {
|
|
13
|
+
type: "object";
|
|
14
|
+
properties: {
|
|
15
|
+
model: {
|
|
16
|
+
type: "string";
|
|
17
|
+
description: string;
|
|
18
|
+
};
|
|
19
|
+
authMode?: {
|
|
20
|
+
type: "string";
|
|
21
|
+
description: string;
|
|
22
|
+
enum: string[];
|
|
23
|
+
default: string;
|
|
24
|
+
} | undefined;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
toolDefinitions: {
|
|
28
|
+
create_channel: {
|
|
29
|
+
description: string;
|
|
30
|
+
inputSchema: import("zod").ZodObject<{
|
|
31
|
+
channelId: import("zod").ZodString;
|
|
32
|
+
spec: import("zod").ZodOptional<import("zod").ZodString>;
|
|
33
|
+
initialState: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
34
|
+
cwd: import("zod").ZodOptional<import("zod").ZodString>;
|
|
35
|
+
}, import("zod/v4/core").$strip>;
|
|
36
|
+
};
|
|
37
|
+
patch_channel_details: {
|
|
38
|
+
description: string;
|
|
39
|
+
inputSchema: import("zod").ZodObject<{
|
|
40
|
+
state: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
41
|
+
spec: import("zod").ZodOptional<import("zod").ZodString>;
|
|
42
|
+
cwd: import("zod").ZodOptional<import("zod").ZodString>;
|
|
43
|
+
}, import("zod/v4/core").$strip>;
|
|
44
|
+
};
|
|
45
|
+
patch_thread_details: {
|
|
46
|
+
description: string;
|
|
47
|
+
inputSchema: import("zod").ZodObject<{
|
|
48
|
+
state: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
49
|
+
}, import("zod/v4/core").$strip>;
|
|
50
|
+
};
|
|
51
|
+
create_variable: {
|
|
52
|
+
description: string;
|
|
53
|
+
inputSchema: import("zod").ZodObject<{
|
|
54
|
+
key: import("zod").ZodString;
|
|
55
|
+
value: import("zod").ZodString;
|
|
56
|
+
secret: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
57
|
+
}, import("zod/v4/core").$strip>;
|
|
58
|
+
};
|
|
59
|
+
delete_variable: {
|
|
60
|
+
description: string;
|
|
61
|
+
inputSchema: import("zod").ZodObject<{
|
|
62
|
+
key: import("zod").ZodString;
|
|
63
|
+
}, import("zod/v4/core").$strip>;
|
|
64
|
+
};
|
|
65
|
+
delete_channel: {
|
|
66
|
+
description: string;
|
|
67
|
+
inputSchema: import("zod").ZodObject<{
|
|
68
|
+
channelId: import("zod").ZodString;
|
|
69
|
+
}, import("zod/v4/core").$strip>;
|
|
70
|
+
};
|
|
71
|
+
get_workspace_file_url: {
|
|
72
|
+
description: string;
|
|
73
|
+
inputSchema: import("zod").ZodObject<{
|
|
74
|
+
path: import("zod").ZodString;
|
|
75
|
+
}, import("zod/v4/core").$strip>;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
factory: (context: import("./types.js").PluginContext) => (builder: import("melony").MelonyBuilder<import("@meetopenbot/plugin-sdk").OpenBotState, import("./types.js").OpenBotEvent>) => void;
|
|
79
|
+
};
|
|
80
|
+
export default openbotPlugin;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { defineOpenbotPlugin } from './types.js';
|
|
2
|
+
import { isCloudMode } from './cloud-mode.js';
|
|
3
|
+
import { openbotRuntime } from './runtime.js';
|
|
4
|
+
import { bashPlugin } from './tools/bash.js';
|
|
5
|
+
import { memoryPlugin } from './tools/memory.js';
|
|
6
|
+
import { todoPlugin } from './tools/todo.js';
|
|
7
|
+
import { approvalPlugin } from './tools/approval.js';
|
|
8
|
+
import { delegationPlugin } from './tools/delegation.js';
|
|
9
|
+
import { uiPlugin } from './tools/ui.js';
|
|
10
|
+
import { previewPlugin } from './tools/preview.js';
|
|
11
|
+
import { storageToolPlugin } from './tools/storage.js';
|
|
12
|
+
export const OPENBOT_PLUGIN_ID = '@meetopenbot/openbot';
|
|
13
|
+
/**
|
|
14
|
+
* `@meetopenbot/openbot` — the standard, opinionated OpenBot agent runtime.
|
|
15
|
+
*
|
|
16
|
+
* Batteries-included: shell, memory, todo, storage tools, delegation, approval,
|
|
17
|
+
* preview, and the LLM loop.
|
|
18
|
+
*/
|
|
19
|
+
export const openbotPlugin = defineOpenbotPlugin({
|
|
20
|
+
id: OPENBOT_PLUGIN_ID,
|
|
21
|
+
name: 'OpenBot Agent',
|
|
22
|
+
description: 'The standard OpenBot agent runtime with inbuilt tools (shell, memory, todo, storage, delegation, and approval).',
|
|
23
|
+
configSchema: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {
|
|
26
|
+
...(isCloudMode()
|
|
27
|
+
? {
|
|
28
|
+
authMode: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'Credits — use your workspace credit balance via OpenBot. BYOK — bring your own API key.',
|
|
31
|
+
enum: ['credits', 'byok'],
|
|
32
|
+
default: 'credits',
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
: {}),
|
|
36
|
+
model: {
|
|
37
|
+
type: 'string',
|
|
38
|
+
description: 'Model from the hosted marketplace registry.',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
toolDefinitions: {
|
|
43
|
+
...bashPlugin.toolDefinitions,
|
|
44
|
+
...memoryPlugin.toolDefinitions,
|
|
45
|
+
...todoPlugin.toolDefinitions,
|
|
46
|
+
...storageToolPlugin.toolDefinitions,
|
|
47
|
+
...delegationPlugin.toolDefinitions,
|
|
48
|
+
...previewPlugin.toolDefinitions,
|
|
49
|
+
},
|
|
50
|
+
factory: (context) => (builder) => {
|
|
51
|
+
const { agentId, config, storage, tools, abortSignal, host } = context;
|
|
52
|
+
bashPlugin.factory(context)(builder);
|
|
53
|
+
memoryPlugin.factory(context)(builder);
|
|
54
|
+
todoPlugin.factory(context)(builder);
|
|
55
|
+
storageToolPlugin.register(context)(builder);
|
|
56
|
+
delegationPlugin.factory(context)(builder);
|
|
57
|
+
uiPlugin.factory(context)(builder);
|
|
58
|
+
previewPlugin.factory(context)(builder);
|
|
59
|
+
const approvalConfig = config?.approval ?? {
|
|
60
|
+
actions: [],
|
|
61
|
+
};
|
|
62
|
+
approvalPlugin.factory({ ...context, config: approvalConfig })(builder);
|
|
63
|
+
const authMode = host.isCloudSystemAgent(agentId)
|
|
64
|
+
? host.parseOpenbotAuthMode(config?.authMode)
|
|
65
|
+
: 'byok';
|
|
66
|
+
return openbotRuntime({
|
|
67
|
+
model: config?.model,
|
|
68
|
+
authMode,
|
|
69
|
+
agentId,
|
|
70
|
+
storage,
|
|
71
|
+
toolDefinitions: tools,
|
|
72
|
+
abortSignal,
|
|
73
|
+
host,
|
|
74
|
+
})(builder);
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
export default openbotPlugin;
|
package/dist/model.d.ts
ADDED
package/dist/model.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { openai as defaultOpenai } from '@ai-sdk/openai';
|
|
2
|
+
import { anthropic } from '@ai-sdk/anthropic';
|
|
3
|
+
import { google } from '@ai-sdk/google';
|
|
4
|
+
export function resolveModel(modelString, _agentId) {
|
|
5
|
+
const [provider, ...rest] = modelString.split('/');
|
|
6
|
+
const modelId = rest.join('/');
|
|
7
|
+
if (!modelId) {
|
|
8
|
+
throw new Error(`Invalid model string: "${modelString}". Expected "provider/model-id".`);
|
|
9
|
+
}
|
|
10
|
+
switch (provider) {
|
|
11
|
+
case 'openai':
|
|
12
|
+
return defaultOpenai(modelId);
|
|
13
|
+
case 'anthropic':
|
|
14
|
+
return anthropic(modelId);
|
|
15
|
+
case 'google':
|
|
16
|
+
return google(modelId);
|
|
17
|
+
default:
|
|
18
|
+
throw new Error(`Unsupported AI provider: "${provider}"`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PluginHost, PluginFactory } from './types.js';
|
|
2
|
+
export interface OpenBotRuntimeOptions {
|
|
3
|
+
/** Provider model string (e.g. `openai/gpt-4o-mini`, `anthropic/claude-3-5-sonnet-20240620`). */
|
|
4
|
+
model?: string;
|
|
5
|
+
/** Cloud system agent auth mode; self-hosted agents always use BYOK. */
|
|
6
|
+
authMode?: 'credits' | 'byok';
|
|
7
|
+
agentId?: string;
|
|
8
|
+
storage?: Record<string, any>;
|
|
9
|
+
/** Tool definitions merged from all tool plugins attached to this agent. */
|
|
10
|
+
toolDefinitions?: Record<string, {
|
|
11
|
+
description: string;
|
|
12
|
+
inputSchema: unknown;
|
|
13
|
+
}>;
|
|
14
|
+
/** Fires when the run is stopped; cancels the in-flight LLM call. */
|
|
15
|
+
abortSignal?: AbortSignal;
|
|
16
|
+
host: PluginHost;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* OpenBot agent runtime.
|
|
20
|
+
*
|
|
21
|
+
* - One `generateText` call per `runLLM` (tools have no `execute`; SDK stops at 1 step).
|
|
22
|
+
* - Tool calls become `action:*` events; plugins emit `:result` when done.
|
|
23
|
+
* - When a full batch of results is in, `runLLM` runs again with updated history.
|
|
24
|
+
*/
|
|
25
|
+
export declare const openbotRuntime: (options: OpenBotRuntimeOptions) => PluginFactory;
|