openbot 0.4.7 → 0.5.5

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.
Files changed (139) hide show
  1. package/.claude/agents/runtime-security-reviewer.md +32 -0
  2. package/.claude/hooks/format.sh +18 -0
  3. package/.claude/hooks/protect-secrets.sh +23 -0
  4. package/.claude/settings.json +26 -0
  5. package/.claude/skills/deploy/SKILL.md +26 -0
  6. package/.claude/skills/new-plugin/SKILL.md +46 -0
  7. package/.dockerignore +9 -0
  8. package/.mcp.json +8 -0
  9. package/AGENTS.md +2 -2
  10. package/CLAUDE.md +51 -0
  11. package/Dockerfile +41 -0
  12. package/deploy/README.md +59 -0
  13. package/deploy/entrypoint.sh +6 -0
  14. package/deploy/fly.toml +36 -0
  15. package/dist/app/bootstrap.js +29 -0
  16. package/dist/app/cli.js +5 -1
  17. package/dist/app/cloud-mode.js +15 -0
  18. package/dist/app/config.js +61 -16
  19. package/dist/app/ensure-default-stack.js +54 -0
  20. package/dist/app/openbot-plugin.js +4 -0
  21. package/dist/app/server.js +37 -6
  22. package/dist/harness/index.js +3 -0
  23. package/dist/plugins/approval/index.js +1 -1
  24. package/dist/plugins/bash/index.js +386 -164
  25. package/dist/plugins/memory/service.js +2 -5
  26. package/dist/plugins/openbot/context.js +17 -1
  27. package/dist/plugins/openbot/index.js +23 -7
  28. package/dist/plugins/openbot/model.js +20 -0
  29. package/dist/plugins/openbot/runtime.js +45 -57
  30. package/dist/plugins/openbot/system-prompt.js +43 -8
  31. package/dist/plugins/preview/index.js +267 -0
  32. package/dist/plugins/storage/index.js +3 -325
  33. package/dist/plugins/storage/service.js +61 -18
  34. package/dist/plugins/todo/index.js +131 -38
  35. package/dist/plugins/todo/service.js +93 -0
  36. package/dist/plugins/ui/index.js +8 -1
  37. package/dist/services/plugins/host.js +21 -0
  38. package/dist/services/plugins/model-registry.js +126 -0
  39. package/dist/services/plugins/registry.js +28 -42
  40. package/dist/services/plugins/service.js +2 -6
  41. package/docs/agents.md +20 -2
  42. package/docs/architecture.md +1 -1
  43. package/docs/plugins.md +13 -3
  44. package/docs/templates/AGENT.example.md +8 -14
  45. package/package.json +5 -2
  46. package/pnpm-workspace.yaml +2 -0
  47. package/src/app/bootstrap.ts +43 -0
  48. package/src/app/cli.ts +5 -1
  49. package/src/app/cloud-mode.ts +26 -0
  50. package/src/app/config.ts +71 -19
  51. package/src/app/ensure-default-stack.ts +63 -0
  52. package/src/app/openbot-plugin.ts +5 -0
  53. package/src/app/server.ts +42 -6
  54. package/src/app/types.ts +158 -32
  55. package/src/harness/index.ts +4 -0
  56. package/src/plugins/memory/service.ts +2 -5
  57. package/src/plugins/storage/index.ts +3 -371
  58. package/src/plugins/storage/service.ts +81 -22
  59. package/src/services/plugins/domain.ts +2 -0
  60. package/src/services/plugins/host.ts +36 -0
  61. package/src/services/plugins/model-registry.ts +178 -0
  62. package/src/services/plugins/registry.ts +30 -43
  63. package/src/services/plugins/service.ts +8 -17
  64. package/src/services/plugins/types.ts +36 -2
  65. package/src/services/todo/types.ts +12 -0
  66. package/dist/agents/openbot/index.js +0 -76
  67. package/dist/agents/openbot/middleware/approval.js +0 -132
  68. package/dist/agents/openbot/runtime.js +0 -289
  69. package/dist/agents/openbot/system-prompt.js +0 -32
  70. package/dist/agents/openbot/tools/delegation.js +0 -78
  71. package/dist/agents/openbot/tools/mcp.js +0 -99
  72. package/dist/agents/openbot/tools/shell.js +0 -91
  73. package/dist/agents/openbot/tools/storage.js +0 -75
  74. package/dist/agents/openbot/tools/ui.js +0 -176
  75. package/dist/agents/system.js +0 -33
  76. package/dist/bus/agent-package.js +0 -1
  77. package/dist/bus/plugin.js +0 -1
  78. package/dist/bus/services.js +0 -754
  79. package/dist/harness/agent-harness.js +0 -45
  80. package/dist/harness/agent-invoke-run.js +0 -44
  81. package/dist/harness/agent-turn.js +0 -99
  82. package/dist/harness/channel-participants.js +0 -40
  83. package/dist/harness/constants.js +0 -2
  84. package/dist/harness/context-meter.js +0 -97
  85. package/dist/harness/context.js +0 -363
  86. package/dist/harness/dispatch.js +0 -144
  87. package/dist/harness/dispatcher.js +0 -156
  88. package/dist/harness/event-normalizer.js +0 -59
  89. package/dist/harness/history.js +0 -177
  90. package/dist/harness/mcp.js +0 -61
  91. package/dist/harness/orchestration.js +0 -88
  92. package/dist/harness/orchestrator.js +0 -149
  93. package/dist/harness/participants.js +0 -22
  94. package/dist/harness/process.js +0 -29
  95. package/dist/harness/queue-processor.js +0 -187
  96. package/dist/harness/run-harness.js +0 -154
  97. package/dist/harness/run.js +0 -98
  98. package/dist/harness/runtime-factory.js +0 -73
  99. package/dist/harness/runtime.js +0 -57
  100. package/dist/harness/todo-advance.js +0 -93
  101. package/dist/harness/todo-dispatch.js +0 -51
  102. package/dist/harness/todos.js +0 -5
  103. package/dist/harness/turn.js +0 -79
  104. package/dist/harness/types.js +0 -1
  105. package/dist/plugins/ai-sdk/index.js +0 -34
  106. package/dist/plugins/ai-sdk/runtime.js +0 -395
  107. package/dist/plugins/ai-sdk/system-prompt.js +0 -18
  108. package/dist/plugins/ai-sdk.js +0 -331
  109. package/dist/plugins/approval.js +0 -163
  110. package/dist/plugins/delegation.js +0 -108
  111. package/dist/plugins/mcp/index.js +0 -108
  112. package/dist/plugins/mcp.js +0 -140
  113. package/dist/plugins/shell/index.js +0 -100
  114. package/dist/plugins/shell.js +0 -123
  115. package/dist/plugins/storage-tools/index.js +0 -76
  116. package/dist/plugins/storage.js +0 -737
  117. package/dist/plugins/thread-namer/index.js +0 -72
  118. package/dist/plugins/threads/index.js +0 -114
  119. package/dist/plugins/ui.js +0 -211
  120. package/dist/plugins/workflow/index.js +0 -65
  121. package/dist/registry/agents.js +0 -138
  122. package/dist/registry/plugins.js +0 -110
  123. package/dist/services/agent-packages.js +0 -103
  124. package/dist/services/memory.js +0 -152
  125. package/dist/services/plugins.js +0 -98
  126. package/dist/services/storage.js +0 -1028
  127. package/dist/workflow/service.js +0 -106
  128. package/dist/workflow/types.js +0 -3
  129. package/src/plugins/approval/index.ts +0 -147
  130. package/src/plugins/bash/index.ts +0 -232
  131. package/src/plugins/delegation/index.ts +0 -153
  132. package/src/plugins/memory/index.ts +0 -182
  133. package/src/plugins/openbot/context.ts +0 -121
  134. package/src/plugins/openbot/history.ts +0 -158
  135. package/src/plugins/openbot/index.ts +0 -80
  136. package/src/plugins/openbot/runtime.ts +0 -526
  137. package/src/plugins/openbot/system-prompt.ts +0 -22
  138. package/src/plugins/ui/index.ts +0 -123
  139. /package/dist/{bus → services/todo}/types.js +0 -0
@@ -1,182 +0,0 @@
1
- import z from 'zod';
2
- import type { Plugin } from '../../services/plugins/types.js';
3
- import { OpenBotEvent, MemoryScopeAlias } from '../../app/types.js';
4
-
5
- /**
6
- * Resolve a scope alias to a concrete scope string. Aliases let tools accept
7
- * `agent`/`channel`/`global` without knowing the active ids; the bus rewrites
8
- * them using `context.state`.
9
- */
10
- function resolveMemoryScope(
11
- alias: MemoryScopeAlias | undefined,
12
- state: any,
13
- ): string {
14
- switch (alias) {
15
- case 'agent':
16
- return `agent:${state.agentId}`;
17
- case 'channel':
18
- return `channel:${state.channelId}`;
19
- case 'global':
20
- case undefined:
21
- return 'global';
22
- default:
23
- return 'global';
24
- }
25
- }
26
-
27
- function resolveMemoryScopeFilter(
28
- alias: MemoryScopeAlias | 'all' | undefined,
29
- state: any,
30
- ): string[] | undefined {
31
- if (alias === 'all' || alias === undefined) {
32
- return ['global', `agent:${state.agentId}`, `channel:${state.channelId}`];
33
- }
34
- return [resolveMemoryScope(alias, state)];
35
- }
36
-
37
- /**
38
- * `memory` — exposes the global memory store as agent tools and provides
39
- * platform-level memory handlers.
40
- */
41
- const memoryToolDefinitions = {
42
- remember: {
43
- description:
44
- 'Persist a durable fact, preference, or note to long-term memory so it can be recalled in future turns and runs. Use for stable information (user preferences, project conventions, contact details, decisions); avoid using it for transient chatter or per-step scratch state — that belongs in thread state. Keep entries short and self-contained.',
45
- inputSchema: z.object({
46
- content: z
47
- .string()
48
- .min(1)
49
- .describe(
50
- 'The fact to remember, written so it makes sense out of context (e.g. "User prefers TypeScript over JavaScript.").',
51
- ),
52
- scope: z
53
- .enum(['global', 'agent', 'channel'])
54
- .optional()
55
- .describe(
56
- 'Visibility: `global` (default, all agents everywhere), `agent` (only this agent), `channel` (only this channel).',
57
- ),
58
- tags: z
59
- .array(z.string())
60
- .optional()
61
- .describe('Optional tags for filtering with `recall`.'),
62
- }),
63
- },
64
- recall: {
65
- description:
66
- 'Search long-term memory for facts you previously stored with `remember`. Returns up to `limit` matching records with their ids so you can `forget` stale ones.',
67
- inputSchema: z.object({
68
- query: z
69
- .string()
70
- .optional()
71
- .describe('Case-insensitive substring filter against memory content.'),
72
- tag: z.string().optional().describe('Only return memories that include this tag.'),
73
- scope: z
74
- .enum(['global', 'agent', 'channel', 'all'])
75
- .optional()
76
- .describe(
77
- 'Restrict the search to a single scope. Default `all` returns global + this agent + this channel.',
78
- ),
79
- limit: z
80
- .number()
81
- .int()
82
- .positive()
83
- .max(50)
84
- .optional()
85
- .describe('Maximum records to return (default 20, max 50).'),
86
- }),
87
- },
88
- forget: {
89
- description:
90
- 'Delete a memory by id. Use after the user asks to forget something or when a previously remembered fact is now wrong. Get ids from `recall`.',
91
- inputSchema: z.object({
92
- id: z.string().describe('The memory record id (returned by `recall`/`remember`).'),
93
- }),
94
- },
95
- };
96
-
97
- export const memoryPlugin: Plugin = {
98
- id: 'memory',
99
- name: 'Memory',
100
- description:
101
- 'Global long-term memory: remember/recall/forget facts across runs and agents.',
102
- toolDefinitions: memoryToolDefinitions,
103
- factory: ({ storage }) => (builder) => {
104
- builder.on('action:remember', async function* (event, context) {
105
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
106
- try {
107
- const { content, scope, tags } = event.data;
108
- const record = await storage.appendMemory({
109
- scope: resolveMemoryScope(scope, context.state),
110
- content,
111
- tags,
112
- });
113
- yield {
114
- type: 'action:remember:result',
115
- data: { success: true, record },
116
- meta: resultMeta,
117
- } as OpenBotEvent;
118
- } catch (error) {
119
- yield {
120
- type: 'action:remember:result',
121
- data: {
122
- success: false,
123
- error: error instanceof Error ? error.message : 'Unknown error',
124
- },
125
- meta: resultMeta,
126
- } as OpenBotEvent;
127
- }
128
- });
129
-
130
- builder.on('action:recall', async function* (event, context) {
131
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
132
- try {
133
- const { query, tag, scope, limit } = event.data;
134
- const records = await storage.listMemories({
135
- scopes: resolveMemoryScopeFilter(scope, context.state),
136
- query,
137
- tag,
138
- limit,
139
- });
140
- yield {
141
- type: 'action:recall:result',
142
- data: { success: true, records },
143
- meta: resultMeta,
144
- } as OpenBotEvent;
145
- } catch (error) {
146
- yield {
147
- type: 'action:recall:result',
148
- data: {
149
- success: false,
150
- records: [],
151
- error: error instanceof Error ? error.message : 'Unknown error',
152
- },
153
- meta: resultMeta,
154
- } as OpenBotEvent;
155
- }
156
- });
157
-
158
- builder.on('action:forget', async function* (event, context) {
159
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
160
- try {
161
- const deleted = await storage.deleteMemory({ id: event.data.id });
162
- yield {
163
- type: 'action:forget:result',
164
- data: { success: true, deleted },
165
- meta: resultMeta,
166
- } as OpenBotEvent;
167
- } catch (error) {
168
- yield {
169
- type: 'action:forget:result',
170
- data: {
171
- success: false,
172
- deleted: false,
173
- error: error instanceof Error ? error.message : 'Unknown error',
174
- },
175
- meta: resultMeta,
176
- } as OpenBotEvent;
177
- }
178
- });
179
- },
180
- };
181
-
182
- export default memoryPlugin;
@@ -1,121 +0,0 @@
1
- import { OpenBotState } from '../../app/types.js';
2
- import { Storage } from '../../services/plugins/domain.js';
3
- import { OPENBOT_SYSTEM_PROMPT } from './system-prompt.js';
4
-
5
- export const DEFAULT_CONTEXT_BUDGET = 8000;
6
- export const MAX_CONTEXT_FILES = 50;
7
-
8
- /**
9
- * Returns the known context window budget (in tokens) for a given model string.
10
- */
11
- export const getContextBudgetForModel = (modelString: string): number => {
12
- const budgets: Record<string, number> = {
13
- 'openai/gpt-4o': 128000,
14
- 'openai/gpt-4o-mini': 128000,
15
- 'openai/o1-preview': 128000,
16
- 'openai/o1-mini': 128000,
17
- 'anthropic/claude-3-5-sonnet-20240620': 200000,
18
- 'anthropic/claude-3-5-sonnet-latest': 200000,
19
- 'anthropic/claude-3-opus-20240229': 200000,
20
- 'anthropic/claude-3-sonnet-20240229': 200000,
21
- 'anthropic/claude-3-haiku-20240307': 200000,
22
- };
23
-
24
- return budgets[modelString] || DEFAULT_CONTEXT_BUDGET;
25
- };
26
-
27
- /** Built-in orchestrator agent id. */
28
- export const ORCHESTRATOR_AGENT_ID = 'system';
29
-
30
- /**
31
- * Simplified context builder for MVP.
32
- */
33
- export async function buildContext(state: OpenBotState, storage?: Storage): Promise<string> {
34
- const { channelId, threadId, channelDetails, agentId, threadDetails, agentDetails } = state;
35
-
36
- const sections: string[] = [];
37
-
38
- // Fetch agents once if storage is available
39
- const allAgents = storage?.getAgents ? await storage.getAgents().catch(() => []) : [];
40
-
41
- // 1. User
42
- if (state.currentUser?.userName) {
43
- sections.push(`## HUMAN\n- Name: ${state.currentUser.userName}`);
44
- }
45
-
46
- // 2. Environment
47
- let env = '## ENVIRONMENT\n';
48
- const channelName = channelDetails?.name || channelId;
49
- env += `- Mode: Channel (#${channelName})\n`;
50
- if (channelDetails?.cwd) {
51
- env += `- Workspace: ${channelDetails.cwd}\n`;
52
- }
53
- if (threadId) {
54
- env += `- Thread: ${threadDetails?.name || threadId}\n`;
55
- }
56
- sections.push(env);
57
-
58
- // 2.5 Installed Agents
59
- if (allAgents.length > 0) {
60
- const formatted = allAgents
61
- .map((a) => `- ${a.id}: ${a.name}${a.description ? ` - ${a.description}` : ''}`)
62
- .join('\n');
63
- sections.push(`## INSTALLED AGENTS\n${formatted}`);
64
- }
65
-
66
- // 3. Channel Spec
67
- const spec = channelDetails?.spec?.trim();
68
- if (spec) {
69
- sections.push(`## CHANNEL SPECIFICATION\n${spec}`);
70
- }
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
- } else {
87
- sections.push('## FILES\n- (No files in workspace)');
88
- }
89
- } catch (error) {
90
- console.warn('[context] Failed to fetch files:', error);
91
- }
92
- }
93
-
94
- // 5. Agent Instructions
95
- const rawInstructions = agentDetails?.instructions?.trim();
96
- if (
97
- rawInstructions &&
98
- rawInstructions !== OPENBOT_SYSTEM_PROMPT.trim()
99
- ) {
100
- sections.push(`## Instructions\n${rawInstructions}`);
101
- }
102
-
103
- // 6. Memories
104
- if (storage?.listMemories) {
105
- try {
106
- const scopes = ['global', `agent:${agentId}`];
107
- if (channelId) scopes.push(`channel:${channelId}`);
108
- const records = await storage.listMemories({ scopes, limit: 20 });
109
- if (records.length > 0) {
110
- const formatted = records
111
- .map((r: any) => `- (${r.scope}) ${r.content}`)
112
- .join('\n');
113
- sections.push(`## MEMORIES\n${formatted}`);
114
- }
115
- } catch (error) {
116
- console.warn('[context] Failed to fetch memories:', error);
117
- }
118
- }
119
-
120
- return sections.join('\n\n');
121
- }
@@ -1,158 +0,0 @@
1
- import { OpenBotEvent } from '../../app/types.js';
2
- import { ToolResultPart, type ModelMessage } from 'ai';
3
-
4
- /**
5
- * Ensures every tool-call has a matching tool-result before calling the LLM.
6
- * Orphaned calls (interrupted run, missing :result event, etc.) get an empty
7
- * result so the conversation can resume instead of failing validation.
8
- */
9
- function fillMissingToolResults(messages: ModelMessage[]): ModelMessage[] {
10
- const filled: ModelMessage[] = [];
11
- const pending = new Map<string, string>();
12
-
13
- const flushPending = () => {
14
- if (pending.size === 0) return;
15
- filled.push({
16
- role: 'tool',
17
- content: [...pending.entries()].map(([toolCallId, toolName]) => ({
18
- type: 'tool-result' as const,
19
- toolCallId,
20
- toolName,
21
- output: { type: 'text' as const, value: '' },
22
- })),
23
- });
24
- pending.clear();
25
- };
26
-
27
- for (const message of messages) {
28
- if (message.role === 'tool' && Array.isArray(message.content)) {
29
- filled.push(message);
30
- for (const part of message.content) {
31
- if ((part as ToolResultPart).type === 'tool-result') {
32
- pending.delete((part as ToolResultPart).toolCallId);
33
- }
34
- }
35
- continue;
36
- }
37
-
38
- flushPending();
39
- filled.push(message);
40
-
41
- if (message.role === 'assistant' && Array.isArray(message.content)) {
42
- for (const part of message.content) {
43
- if ((part as { type?: string; toolCallId?: string; toolName?: string }).type === 'tool-call') {
44
- const toolCall = part as { toolCallId: string; toolName: string };
45
- pending.set(toolCall.toolCallId, toolCall.toolName);
46
- }
47
- }
48
- }
49
- }
50
-
51
- flushPending();
52
- return filled;
53
- }
54
-
55
- /**
56
- * Converts a raw event log into a valid chain of ModelMessages for the AI SDK.
57
- *
58
- * This is a basic implementation that maps events to messages and filters out
59
- * events from sub-processes (delegation) to avoid duplication in history.
60
- */
61
- export function eventsToModelMessages(events: OpenBotEvent[]): ModelMessage[] {
62
- const messages: ModelMessage[] = [];
63
-
64
- for (const event of events) {
65
- // Skip events that belong to a sub-process (like delegation)
66
- // so they don't pollute the main conversation history.
67
- if (event.meta?.parentToolCallId) {
68
- continue;
69
- }
70
-
71
- switch (event.type) {
72
- case 'agent:output': {
73
- const last = messages[messages.length - 1];
74
- if (last && last.role === 'assistant' && typeof last.content === 'string') {
75
- last.content += event.data.content;
76
- } else {
77
- messages.push({ role: 'assistant', content: event.data.content });
78
- }
79
- break;
80
- }
81
-
82
- case 'agent:invoke': {
83
- const invokeEvent = event as any;
84
- if (invokeEvent.data?.content && invokeEvent.data?.role) {
85
- messages.push({
86
- role: invokeEvent.data.role,
87
- content: invokeEvent.data.content
88
- } as ModelMessage);
89
- }
90
- break;
91
- }
92
-
93
- default:
94
- // Handle tool calls (action:*)
95
- if (event.type.startsWith('action:') && !event.type.endsWith(':result')) {
96
-
97
-
98
- const toolName = event.type.slice(7);
99
- const toolCallId = event.meta?.toolCallId;
100
- if (!toolCallId) break;
101
-
102
- const toolCall = {
103
- type: 'tool-call' as const,
104
- toolCallId,
105
- toolName,
106
- input: (event as any).data,
107
- };
108
-
109
- const last = messages[messages.length - 1];
110
-
111
- if (last && last.role === 'assistant') {
112
- if (typeof last.content === 'string') {
113
- last.content = [
114
- { type: 'text', text: last.content },
115
- toolCall,
116
- ];
117
- } else if (Array.isArray(last.content)) {
118
- (last.content as any[]).push(toolCall);
119
- }
120
- } else {
121
- messages.push({
122
- role: 'assistant',
123
- content: [toolCall],
124
- });
125
- }
126
- }
127
- // Handle tool results (action:*:result)
128
- else if (event.type.startsWith('action:') && event.type.endsWith(':result')) {
129
- const toolName = event.type.slice(7, -7);
130
- const toolCallId = event.meta?.toolCallId;
131
- if (!toolCallId) break;
132
-
133
- const toolResult: ToolResultPart = {
134
- type: 'tool-result' as const,
135
- toolCallId,
136
- toolName,
137
- output: {
138
- type: 'text',
139
- value: (event as any)?.data?.output || "No output", // ?.output is from delegation result
140
- },
141
- };
142
-
143
- const last = messages[messages.length - 1];
144
- if (last && last.role === 'tool' && Array.isArray(last.content)) {
145
- (last.content as any[]).push(toolResult);
146
- } else {
147
- messages.push({
148
- role: 'tool',
149
- content: [toolResult],
150
- });
151
- }
152
- }
153
- break;
154
- }
155
- }
156
-
157
- return fillMissingToolResults(messages);
158
- }
@@ -1,80 +0,0 @@
1
- import type { Plugin } from '../../services/plugins/types.js';
2
- import { openbotRuntime } from './runtime.js';
3
- import { bashPlugin } from '../bash/index.js';
4
- import { memoryPlugin } from '../memory/index.js';
5
- import { approvalPlugin } from '../approval/index.js';
6
- import { storagePlugin } from '../storage/index.js';
7
- import { delegationPlugin } from '../delegation/index.js';
8
- import { uiPlugin } from '../ui/index.js';
9
-
10
- /**
11
- * `openbot` — the standard, opinionated OpenBot agent runtime.
12
- *
13
- * This is the canonical execution loop for OpenBot agents. It handles
14
- * `agent:invoke`, manages short-term memory, assembles context, and
15
- * orchestrates tool calls.
16
- *
17
- * It comes with a "batteries-included" set of inbuilt tools: bash, memory,
18
- * storage, delegation, and approval.
19
- */
20
- export const openbotPlugin: Plugin = {
21
- id: 'openbot',
22
- name: 'OpenBot Agent',
23
- description:
24
- 'The standard OpenBot agent runtime with inbuilt tools (bash, memory, storage, delegation, and approval).',
25
- configSchema: {
26
- type: 'object',
27
- properties: {
28
- model: {
29
- type: 'string',
30
- description:
31
- 'Provider model string, e.g. openai/gpt-4o-mini, anthropic/claude-3-5-sonnet-20240620',
32
- default: 'openai/gpt-4o-mini',
33
- },
34
- approval: {
35
- type: 'object',
36
- description: 'Configuration for the inbuilt approval plugin.',
37
- properties: {
38
- actions: {
39
- type: 'array',
40
- items: { type: 'string' },
41
- description: 'List of actions that require manual approval.',
42
- },
43
- },
44
- },
45
- },
46
- },
47
- toolDefinitions: {
48
- ...bashPlugin.toolDefinitions,
49
- ...memoryPlugin.toolDefinitions,
50
- ...storagePlugin.toolDefinitions,
51
- ...delegationPlugin.toolDefinitions,
52
- // this is the capability to render UI widgets to the user. We dont need it for now.
53
- // ...uiPlugin.toolDefinitions,
54
- },
55
- factory: (context) => (builder) => {
56
- const { config, storage, tools, abortSignal } = context;
57
-
58
- // Register inbuilt plugins
59
- bashPlugin.factory(context)(builder);
60
- memoryPlugin.factory(context)(builder);
61
- storagePlugin.factory(context)(builder);
62
- delegationPlugin.factory(context)(builder);
63
- uiPlugin.factory(context)(builder);
64
-
65
- // Approval plugin configuration
66
- const approvalConfig = (config?.approval as any) || {
67
- actions: ['action:bash', 'action:create_channel', 'action:delete_channel'],
68
- };
69
- approvalPlugin.factory({ ...context, config: approvalConfig })(builder);
70
-
71
- return openbotRuntime({
72
- model: config?.model as string,
73
- storage,
74
- toolDefinitions: tools,
75
- abortSignal,
76
- })(builder);
77
- },
78
- };
79
-
80
- export default openbotPlugin;